Use native radiobutton for Default Search Engine picker dialog.
[chromium-blink-merge.git] / content / browser / gpu / browser_gpu_channel_host_factory.cc
blob11bbe83fc2f56a68f95de6d33a75ce857aa8fa76
1 // Copyright (c) 2012 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/gpu/browser_gpu_channel_host_factory.h"
7 #include <set>
9 #include "base/bind.h"
10 #include "base/profiler/scoped_tracker.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "base/trace_event/trace_event.h"
14 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
15 #include "content/browser/gpu/gpu_data_manager_impl.h"
16 #include "content/browser/gpu/gpu_process_host.h"
17 #include "content/browser/gpu/gpu_surface_tracker.h"
18 #include "content/common/child_process_host_impl.h"
19 #include "content/common/gpu/gpu_memory_buffer_factory.h"
20 #include "content/common/gpu/gpu_messages.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/gpu_data_manager.h"
23 #include "content/public/common/content_client.h"
24 #include "gpu/GLES2/gl2extchromium.h"
25 #include "ipc/ipc_channel_handle.h"
26 #include "ipc/ipc_forwarding_message_filter.h"
27 #include "ipc/message_filter.h"
29 #if defined(OS_MACOSX)
30 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
31 #endif
33 #if defined(OS_ANDROID)
34 #include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
35 #endif
37 #if defined(USE_OZONE)
38 #include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h"
39 #endif
41 namespace content {
42 namespace {
44 base::LazyInstance<std::set<gfx::GpuMemoryBuffer::Usage>>
45 g_enabled_gpu_memory_buffer_usages;
48 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
50 struct BrowserGpuChannelHostFactory::CreateRequest {
51 CreateRequest(int32 route_id)
52 : event(true, false),
53 gpu_host_id(0),
54 route_id(route_id),
55 result(CREATE_COMMAND_BUFFER_FAILED) {}
56 ~CreateRequest() {}
57 base::WaitableEvent event;
58 int gpu_host_id;
59 int32 route_id;
60 CreateCommandBufferResult result;
63 class BrowserGpuChannelHostFactory::EstablishRequest
64 : public base::RefCountedThreadSafe<EstablishRequest> {
65 public:
66 static scoped_refptr<EstablishRequest> Create(CauseForGpuLaunch cause,
67 int gpu_client_id,
68 int gpu_host_id);
69 void Wait();
70 void Cancel();
72 int gpu_host_id() { return gpu_host_id_; }
73 IPC::ChannelHandle& channel_handle() { return channel_handle_; }
74 gpu::GPUInfo gpu_info() { return gpu_info_; }
76 private:
77 friend class base::RefCountedThreadSafe<EstablishRequest>;
78 explicit EstablishRequest(CauseForGpuLaunch cause,
79 int gpu_client_id,
80 int gpu_host_id);
81 ~EstablishRequest() {}
82 void EstablishOnIO();
83 void OnEstablishedOnIO(const IPC::ChannelHandle& channel_handle,
84 const gpu::GPUInfo& gpu_info);
85 void FinishOnIO();
86 void FinishOnMain();
88 base::WaitableEvent event_;
89 CauseForGpuLaunch cause_for_gpu_launch_;
90 const int gpu_client_id_;
91 int gpu_host_id_;
92 bool reused_gpu_process_;
93 IPC::ChannelHandle channel_handle_;
94 gpu::GPUInfo gpu_info_;
95 bool finished_;
96 scoped_refptr<base::MessageLoopProxy> main_loop_;
99 scoped_refptr<BrowserGpuChannelHostFactory::EstablishRequest>
100 BrowserGpuChannelHostFactory::EstablishRequest::Create(CauseForGpuLaunch cause,
101 int gpu_client_id,
102 int gpu_host_id) {
103 scoped_refptr<EstablishRequest> establish_request =
104 new EstablishRequest(cause, gpu_client_id, gpu_host_id);
105 scoped_refptr<base::MessageLoopProxy> loop =
106 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
107 // PostTask outside the constructor to ensure at least one reference exists.
108 loop->PostTask(
109 FROM_HERE,
110 base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO,
111 establish_request));
112 return establish_request;
115 BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
116 CauseForGpuLaunch cause,
117 int gpu_client_id,
118 int gpu_host_id)
119 : event_(false, false),
120 cause_for_gpu_launch_(cause),
121 gpu_client_id_(gpu_client_id),
122 gpu_host_id_(gpu_host_id),
123 reused_gpu_process_(false),
124 finished_(false),
125 main_loop_(base::MessageLoopProxy::current()) {
128 void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
129 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
130 tracked_objects::ScopedTracker tracking_profile(
131 FROM_HERE_WITH_EXPLICIT_FUNCTION(
132 "477117 "
133 "BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO"));
134 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
135 if (!host) {
136 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
137 cause_for_gpu_launch_);
138 if (!host) {
139 LOG(ERROR) << "Failed to launch GPU process.";
140 FinishOnIO();
141 return;
143 gpu_host_id_ = host->host_id();
144 reused_gpu_process_ = false;
145 } else {
146 if (reused_gpu_process_) {
147 // We come here if we retried to establish the channel because of a
148 // failure in ChannelEstablishedOnIO, but we ended up with the same
149 // process ID, meaning the failure was not because of a channel error,
150 // but another reason. So fail now.
151 LOG(ERROR) << "Failed to create channel.";
152 FinishOnIO();
153 return;
155 reused_gpu_process_ = true;
158 host->EstablishGpuChannel(
159 gpu_client_id_,
160 true,
161 true,
162 base::Bind(
163 &BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO,
164 this));
167 void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO(
168 const IPC::ChannelHandle& channel_handle,
169 const gpu::GPUInfo& gpu_info) {
170 if (channel_handle.name.empty() && reused_gpu_process_) {
171 // We failed after re-using the GPU process, but it may have died in the
172 // mean time. Retry to have a chance to create a fresh GPU process.
173 DVLOG(1) << "Failed to create channel on existing GPU process. Trying to "
174 "restart GPU process.";
175 EstablishOnIO();
176 } else {
177 channel_handle_ = channel_handle;
178 gpu_info_ = gpu_info;
179 FinishOnIO();
183 void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() {
184 event_.Signal();
185 main_loop_->PostTask(
186 FROM_HERE,
187 base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain,
188 this));
191 void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() {
192 if (!finished_) {
193 BrowserGpuChannelHostFactory* factory =
194 BrowserGpuChannelHostFactory::instance();
195 factory->GpuChannelEstablished();
196 finished_ = true;
200 void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
201 DCHECK(main_loop_->BelongsToCurrentThread());
203 // TODO(vadimt): Remove ScopedTracker below once crbug.com/125248 is fixed.
204 tracked_objects::ScopedTracker tracking_profile(
205 FROM_HERE_WITH_EXPLICIT_FUNCTION(
206 "125248 BrowserGpuChannelHostFactory::EstablishRequest::Wait"));
208 // We're blocking the UI thread, which is generally undesirable.
209 // In this case we need to wait for this before we can show any UI
210 // /anyway/, so it won't cause additional jank.
211 // TODO(piman): Make this asynchronous (http://crbug.com/125248).
212 TRACE_EVENT0("browser",
213 "BrowserGpuChannelHostFactory::EstablishGpuChannelSync");
214 base::ThreadRestrictions::ScopedAllowWait allow_wait;
215 event_.Wait();
217 FinishOnMain();
220 void BrowserGpuChannelHostFactory::EstablishRequest::Cancel() {
221 DCHECK(main_loop_->BelongsToCurrentThread());
222 finished_ = true;
225 bool BrowserGpuChannelHostFactory::CanUseForTesting() {
226 return GpuDataManager::GetInstance()->GpuAccessAllowed(NULL);
229 void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) {
230 DCHECK(!instance_);
231 instance_ = new BrowserGpuChannelHostFactory();
232 if (establish_gpu_channel) {
233 instance_->EstablishGpuChannel(CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP,
234 base::Closure());
238 void BrowserGpuChannelHostFactory::Terminate() {
239 DCHECK(instance_);
240 delete instance_;
241 instance_ = NULL;
244 // static
245 void BrowserGpuChannelHostFactory::EnableGpuMemoryBufferFactoryUsage(
246 gfx::GpuMemoryBuffer::Usage usage) {
247 g_enabled_gpu_memory_buffer_usages.Get().insert(usage);
250 // static
251 bool BrowserGpuChannelHostFactory::IsGpuMemoryBufferFactoryUsageEnabled(
252 gfx::GpuMemoryBuffer::Usage usage) {
253 return g_enabled_gpu_memory_buffer_usages.Get().count(usage) != 0;
256 // static
257 uint32 BrowserGpuChannelHostFactory::GetImageTextureTarget() {
258 if (!IsGpuMemoryBufferFactoryUsageEnabled(gfx::GpuMemoryBuffer::MAP))
259 return GL_TEXTURE_2D;
261 std::vector<gfx::GpuMemoryBufferType> supported_types;
262 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types);
263 DCHECK(!supported_types.empty());
265 // The GPU service will always use the preferred type.
266 gfx::GpuMemoryBufferType type = supported_types[0];
268 switch (type) {
269 case gfx::SURFACE_TEXTURE_BUFFER:
270 case gfx::OZONE_NATIVE_BUFFER:
271 // GPU memory buffers that are shared with the GL using EGLImages require
272 // TEXTURE_EXTERNAL_OES.
273 return GL_TEXTURE_EXTERNAL_OES;
274 case gfx::IO_SURFACE_BUFFER:
275 // IOSurface backed images require GL_TEXTURE_RECTANGLE_ARB.
276 return GL_TEXTURE_RECTANGLE_ARB;
277 default:
278 return GL_TEXTURE_2D;
282 BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
283 : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
284 shutdown_event_(new base::WaitableEvent(true, false)),
285 gpu_memory_buffer_manager_(
286 new BrowserGpuMemoryBufferManager(this, gpu_client_id_)),
287 gpu_host_id_(0),
288 next_create_gpu_memory_buffer_request_id_(0) {
291 BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
292 DCHECK(IsMainThread());
293 if (pending_request_.get())
294 pending_request_->Cancel();
295 for (size_t n = 0; n < established_callbacks_.size(); n++)
296 established_callbacks_[n].Run();
297 shutdown_event_->Signal();
298 if (gpu_channel_) {
299 gpu_channel_->DestroyChannel();
300 gpu_channel_ = NULL;
304 bool BrowserGpuChannelHostFactory::IsMainThread() {
305 return BrowserThread::CurrentlyOn(BrowserThread::UI);
308 scoped_refptr<base::MessageLoopProxy>
309 BrowserGpuChannelHostFactory::GetIOLoopProxy() {
310 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
313 scoped_ptr<base::SharedMemory>
314 BrowserGpuChannelHostFactory::AllocateSharedMemory(size_t size) {
315 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
316 if (!shm->CreateAnonymous(size))
317 return scoped_ptr<base::SharedMemory>();
318 return shm.Pass();
321 void BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO(
322 CreateRequest* request,
323 int32 surface_id,
324 const GPUCreateCommandBufferConfig& init_params) {
325 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
326 if (!host) {
327 request->event.Signal();
328 return;
331 gfx::GLSurfaceHandle surface =
332 GpuSurfaceTracker::Get()->GetSurfaceHandle(surface_id);
334 host->CreateViewCommandBuffer(
335 surface,
336 surface_id,
337 gpu_client_id_,
338 init_params,
339 request->route_id,
340 base::Bind(&BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO,
341 request));
344 // static
345 void BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO(
346 CreateRequest* request, CreateCommandBufferResult result) {
347 request->result = result;
348 request->event.Signal();
351 CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
352 int32 surface_id,
353 const GPUCreateCommandBufferConfig& init_params,
354 int32 route_id) {
355 CreateRequest request(route_id);
356 GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
357 &BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO,
358 base::Unretained(this),
359 &request,
360 surface_id,
361 init_params));
362 // TODO(vadimt): Remove ScopedTracker below once crbug.com/125248 is fixed.
363 tracked_objects::ScopedTracker tracking_profile(
364 FROM_HERE_WITH_EXPLICIT_FUNCTION(
365 "125248 BrowserGpuChannelHostFactory::CreateViewCommandBuffer"));
367 // We're blocking the UI thread, which is generally undesirable.
368 // In this case we need to wait for this before we can show any UI /anyway/,
369 // so it won't cause additional jank.
370 // TODO(piman): Make this asynchronous (http://crbug.com/125248).
371 TRACE_EVENT0("browser",
372 "BrowserGpuChannelHostFactory::CreateViewCommandBuffer");
373 base::ThreadRestrictions::ScopedAllowWait allow_wait;
374 request.event.Wait();
375 return request.result;
378 // Blocking the UI thread to open a GPU channel is not supported on Android.
379 // (Opening the initial channel to a child process involves handling a reply
380 // task on the UI thread first, so we cannot block here.)
381 #if !defined(OS_ANDROID)
382 GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
383 CauseForGpuLaunch cause_for_gpu_launch) {
384 EstablishGpuChannel(cause_for_gpu_launch, base::Closure());
386 if (pending_request_.get())
387 pending_request_->Wait();
389 return gpu_channel_.get();
391 #endif
393 void BrowserGpuChannelHostFactory::EstablishGpuChannel(
394 CauseForGpuLaunch cause_for_gpu_launch,
395 const base::Closure& callback) {
396 if (gpu_channel_.get() && gpu_channel_->IsLost()) {
397 DCHECK(!pending_request_.get());
398 // Recreate the channel if it has been lost.
399 gpu_channel_->DestroyChannel();
400 gpu_channel_ = NULL;
403 if (!gpu_channel_.get() && !pending_request_.get()) {
404 // We should only get here if the context was lost.
405 pending_request_ = EstablishRequest::Create(
406 cause_for_gpu_launch, gpu_client_id_, gpu_host_id_);
409 if (!callback.is_null()) {
410 if (gpu_channel_.get())
411 callback.Run();
412 else
413 established_callbacks_.push_back(callback);
417 GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
418 if (gpu_channel_.get() && !gpu_channel_->IsLost())
419 return gpu_channel_.get();
421 return NULL;
424 void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
425 DCHECK(IsMainThread());
426 DCHECK(pending_request_.get());
427 if (pending_request_->channel_handle().name.empty()) {
428 DCHECK(!gpu_channel_.get());
429 } else {
430 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/466866
431 // is fixed.
432 tracked_objects::ScopedTracker tracking_profile1(
433 FROM_HERE_WITH_EXPLICIT_FUNCTION(
434 "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished1"));
435 GetContentClient()->SetGpuInfo(pending_request_->gpu_info());
436 gpu_channel_ =
437 GpuChannelHost::Create(this,
438 pending_request_->gpu_info(),
439 pending_request_->channel_handle(),
440 shutdown_event_.get(),
441 BrowserGpuMemoryBufferManager::current());
443 gpu_host_id_ = pending_request_->gpu_host_id();
444 pending_request_ = NULL;
446 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/466866 is
447 // fixed.
448 tracked_objects::ScopedTracker tracking_profile2(
449 FROM_HERE_WITH_EXPLICIT_FUNCTION(
450 "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished2"));
452 for (size_t n = 0; n < established_callbacks_.size(); n++)
453 established_callbacks_[n].Run();
455 established_callbacks_.clear();
458 // static
459 void BrowserGpuChannelHostFactory::AddFilterOnIO(
460 int host_id,
461 scoped_refptr<IPC::MessageFilter> filter) {
462 DCHECK_CURRENTLY_ON(BrowserThread::IO);
464 GpuProcessHost* host = GpuProcessHost::FromID(host_id);
465 if (host)
466 host->AddFilter(filter.get());
469 bool BrowserGpuChannelHostFactory::IsGpuMemoryBufferConfigurationSupported(
470 gfx::GpuMemoryBuffer::Format format,
471 gfx::GpuMemoryBuffer::Usage usage) {
472 // Return early if usage is not enabled.
473 if (!IsGpuMemoryBufferFactoryUsageEnabled(usage))
474 return false;
476 // Preferred type is always used by factory.
477 std::vector<gfx::GpuMemoryBufferType> supported_types;
478 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types);
479 DCHECK(!supported_types.empty());
480 switch (supported_types[0]) {
481 case gfx::SHARED_MEMORY_BUFFER:
482 // Shared memory buffers must be created in-process.
483 return false;
484 #if defined(OS_MACOSX)
485 case gfx::IO_SURFACE_BUFFER:
486 return GpuMemoryBufferFactoryIOSurface::
487 IsGpuMemoryBufferConfigurationSupported(format, usage);
488 #endif
489 #if defined(OS_ANDROID)
490 case gfx::SURFACE_TEXTURE_BUFFER:
491 return GpuMemoryBufferFactorySurfaceTexture::
492 IsGpuMemoryBufferConfigurationSupported(format, usage);
493 #endif
494 #if defined(USE_OZONE)
495 case gfx::OZONE_NATIVE_BUFFER:
496 return GpuMemoryBufferFactoryOzoneNativeBuffer::
497 IsGpuMemoryBufferConfigurationSupported(format, usage);
498 #endif
499 default:
500 NOTREACHED();
501 return false;
505 void BrowserGpuChannelHostFactory::CreateGpuMemoryBuffer(
506 gfx::GpuMemoryBufferId id,
507 const gfx::Size& size,
508 gfx::GpuMemoryBuffer::Format format,
509 gfx::GpuMemoryBuffer::Usage usage,
510 int client_id,
511 int32 surface_id,
512 const CreateGpuMemoryBufferCallback& callback) {
513 DCHECK_CURRENTLY_ON(BrowserThread::IO);
515 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
516 if (!host) {
517 callback.Run(gfx::GpuMemoryBufferHandle());
518 return;
521 uint32 request_id = next_create_gpu_memory_buffer_request_id_++;
522 create_gpu_memory_buffer_requests_[request_id] = callback;
524 host->CreateGpuMemoryBuffer(
525 id, size, format, usage, client_id, surface_id,
526 base::Bind(&BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated,
527 base::Unretained(this), request_id));
530 void BrowserGpuChannelHostFactory::DestroyGpuMemoryBuffer(
531 gfx::GpuMemoryBufferId id,
532 int client_id,
533 int32 sync_point) {
534 BrowserThread::PostTask(
535 BrowserThread::IO,
536 FROM_HERE,
537 base::Bind(&BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO,
538 base::Unretained(this),
540 client_id,
541 sync_point));
544 void BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO(
545 gfx::GpuMemoryBufferId id,
546 int client_id,
547 int32 sync_point) {
548 DCHECK_CURRENTLY_ON(BrowserThread::IO);
550 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
551 if (!host)
552 return;
554 host->DestroyGpuMemoryBuffer(id, client_id, sync_point);
557 void BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated(
558 uint32 request_id,
559 const gfx::GpuMemoryBufferHandle& handle) {
560 DCHECK_CURRENTLY_ON(BrowserThread::IO);
562 CreateGpuMemoryBufferCallbackMap::iterator iter =
563 create_gpu_memory_buffer_requests_.find(request_id);
564 DCHECK(iter != create_gpu_memory_buffer_requests_.end());
565 iter->second.Run(handle);
566 create_gpu_memory_buffer_requests_.erase(iter);
569 } // namespace content