| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/gpu/gpu_child_thread.h" |
| |
| #include <stddef.h> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/lazy_instance.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/threading/worker_pool.h" |
| #include "build/build_config.h" |
| #include "content/child/child_process.h" |
| #include "content/child/thread_safe_sender.h" |
| #include "content/common/gpu/establish_channel_params.h" |
| #include "content/common/gpu/gpu_host_messages.h" |
| #include "content/common/gpu/gpu_memory_buffer_factory.h" |
| #include "content/common/gpu/media/gpu_video_decode_accelerator.h" |
| #include "content/gpu/gpu_process_control_impl.h" |
| #include "content/gpu/gpu_watchdog_thread.h" |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/gpu/content_gpu_client.h" |
| #include "gpu/command_buffer/service/gpu_switches.h" |
| #include "gpu/config/gpu_info_collector.h" |
| #include "gpu/config/gpu_switches.h" |
| #include "gpu/config/gpu_util.h" |
| #include "ipc/ipc_channel_handle.h" |
| #include "ipc/ipc_sync_message_filter.h" |
| #include "ui/gl/gl_implementation.h" |
| #include "ui/gl/gl_switches.h" |
| #include "ui/gl/gpu_switching_manager.h" |
| |
| #if defined(USE_OZONE) |
| #include "ui/ozone/public/gpu_platform_support.h" |
| #include "ui/ozone/public/ozone_platform.h" |
| #endif |
| |
| namespace content { |
| namespace { |
| |
| static base::LazyInstance<scoped_refptr<ThreadSafeSender> > |
| g_thread_safe_sender = LAZY_INSTANCE_INITIALIZER; |
| |
| bool GetSizeTFromSwitch(const base::CommandLine* command_line, |
| const base::StringPiece& switch_string, |
| size_t* value) { |
| if (!command_line->HasSwitch(switch_string)) |
| return false; |
| std::string switch_value(command_line->GetSwitchValueASCII(switch_string)); |
| return base::StringToSizeT(switch_value, value); |
| } |
| |
| bool GpuProcessLogMessageHandler(int severity, |
| const char* file, int line, |
| size_t message_start, |
| const std::string& str) { |
| std::string header = str.substr(0, message_start); |
| std::string message = str.substr(message_start); |
| |
| g_thread_safe_sender.Get()->Send( |
| new GpuHostMsg_OnLogMessage(severity, header, message)); |
| |
| return false; |
| } |
| |
| // Message filter used to to handle GpuMsg_CreateGpuMemoryBuffer messages |
| // on the IO thread. This allows the UI thread in the browser process to remain |
| // fast at all times. |
| class GpuMemoryBufferMessageFilter : public IPC::MessageFilter { |
| public: |
| explicit GpuMemoryBufferMessageFilter( |
| GpuMemoryBufferFactory* gpu_memory_buffer_factory) |
| : gpu_memory_buffer_factory_(gpu_memory_buffer_factory), |
| sender_(nullptr) {} |
| |
| // Overridden from IPC::MessageFilter: |
| void OnFilterAdded(IPC::Sender* sender) override { |
| DCHECK(!sender_); |
| sender_ = sender; |
| } |
| void OnFilterRemoved() override { |
| DCHECK(sender_); |
| sender_ = nullptr; |
| } |
| bool OnMessageReceived(const IPC::Message& message) override { |
| DCHECK(sender_); |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(GpuMemoryBufferMessageFilter, message) |
| IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer) |
| IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBufferFromHandle, |
| OnCreateGpuMemoryBufferFromHandle) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| protected: |
| ~GpuMemoryBufferMessageFilter() override {} |
| |
| void OnCreateGpuMemoryBuffer( |
| const GpuMsg_CreateGpuMemoryBuffer_Params& params) { |
| TRACE_EVENT2("gpu", "GpuMemoryBufferMessageFilter::OnCreateGpuMemoryBuffer", |
| "id", params.id.id, "client_id", params.client_id); |
| |
| DCHECK(gpu_memory_buffer_factory_); |
| sender_->Send(new GpuHostMsg_GpuMemoryBufferCreated( |
| gpu_memory_buffer_factory_->CreateGpuMemoryBuffer( |
| params.id, params.size, params.format, params.usage, |
| params.client_id, params.surface_handle))); |
| } |
| |
| void OnCreateGpuMemoryBufferFromHandle( |
| const GpuMsg_CreateGpuMemoryBufferFromHandle_Params& params) { |
| TRACE_EVENT2( |
| "gpu", |
| "GpuMemoryBufferMessageFilter::OnCreateGpuMemoryBufferFromHandle", "id", |
| params.id.id, "client_id", params.client_id); |
| sender_->Send(new GpuHostMsg_GpuMemoryBufferCreated( |
| gpu_memory_buffer_factory_->CreateGpuMemoryBufferFromHandle( |
| params.handle, params.id, params.size, params.format, |
| params.client_id))); |
| } |
| |
| GpuMemoryBufferFactory* const gpu_memory_buffer_factory_; |
| IPC::Sender* sender_; |
| }; |
| |
| ChildThreadImpl::Options GetOptions( |
| GpuMemoryBufferFactory* gpu_memory_buffer_factory) { |
| ChildThreadImpl::Options::Builder builder; |
| |
| builder.AddStartupFilter( |
| new GpuMemoryBufferMessageFilter(gpu_memory_buffer_factory)); |
| |
| #if defined(USE_OZONE) |
| IPC::MessageFilter* message_filter = ui::OzonePlatform::GetInstance() |
| ->GetGpuPlatformSupport() |
| ->GetMessageFilter(); |
| if (message_filter) |
| builder.AddStartupFilter(message_filter); |
| #endif |
| |
| return builder.Build(); |
| } |
| |
| } // namespace |
| |
| GpuChildThread::GpuChildThread( |
| GpuWatchdogThread* watchdog_thread, |
| bool dead_on_arrival, |
| const gpu::GPUInfo& gpu_info, |
| const DeferredMessages& deferred_messages, |
| GpuMemoryBufferFactory* gpu_memory_buffer_factory, |
| gpu::SyncPointManager* sync_point_manager) |
| : ChildThreadImpl(GetOptions(gpu_memory_buffer_factory)), |
| gpu_preferences_(GetGpuPreferencesFromCommandLine()), |
| dead_on_arrival_(dead_on_arrival), |
| sync_point_manager_(sync_point_manager), |
| gpu_info_(gpu_info), |
| deferred_messages_(deferred_messages), |
| in_browser_process_(false), |
| gpu_memory_buffer_factory_(gpu_memory_buffer_factory) { |
| watchdog_thread_ = watchdog_thread; |
| #if defined(OS_WIN) |
| target_services_ = NULL; |
| #endif |
| g_thread_safe_sender.Get() = thread_safe_sender(); |
| } |
| |
| GpuChildThread::GpuChildThread( |
| const gpu::GpuPreferences& gpu_preferences, |
| const InProcessChildThreadParams& params, |
| GpuMemoryBufferFactory* gpu_memory_buffer_factory, |
| gpu::SyncPointManager* sync_point_manager) |
| : ChildThreadImpl(ChildThreadImpl::Options::Builder() |
| .InBrowserProcess(params) |
| .AddStartupFilter(new GpuMemoryBufferMessageFilter( |
| gpu_memory_buffer_factory)) |
| .Build()), |
| gpu_preferences_(gpu_preferences), |
| dead_on_arrival_(false), |
| sync_point_manager_(sync_point_manager), |
| in_browser_process_(true), |
| gpu_memory_buffer_factory_(gpu_memory_buffer_factory) { |
| #if defined(OS_WIN) |
| target_services_ = NULL; |
| #endif |
| DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kSingleProcess) || |
| base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kInProcessGPU)); |
| |
| // Populate accelerator capabilities (normally done during GpuMain, which is |
| // not called for single process or in process gpu). |
| gpu_info_.video_decode_accelerator_capabilities = |
| content::GpuVideoDecodeAccelerator::GetCapabilities(); |
| |
| if (!gfx::GLSurface::InitializeOneOff()) |
| VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; |
| |
| g_thread_safe_sender.Get() = thread_safe_sender(); |
| } |
| |
| GpuChildThread::~GpuChildThread() { |
| while (!deferred_messages_.empty()) { |
| delete deferred_messages_.front(); |
| deferred_messages_.pop(); |
| } |
| } |
| |
| void GpuChildThread::Shutdown() { |
| ChildThreadImpl::Shutdown(); |
| logging::SetLogMessageHandler(NULL); |
| } |
| |
| void GpuChildThread::Init(const base::Time& process_start_time) { |
| process_start_time_ = process_start_time; |
| |
| process_control_.reset(new GpuProcessControlImpl()); |
| // Use of base::Unretained(this) is safe here because |service_registry()| |
| // will be destroyed before GpuChildThread is destructed. |
| service_registry()->AddService(base::Bind( |
| &GpuChildThread::BindProcessControlRequest, base::Unretained(this))); |
| |
| if (GetContentClient()->gpu()) // NULL in tests. |
| GetContentClient()->gpu()->RegisterMojoServices(service_registry()); |
| } |
| |
| bool GpuChildThread::Send(IPC::Message* msg) { |
| // The GPU process must never send a synchronous IPC message to the browser |
| // process. This could result in deadlock. |
| DCHECK(!msg->is_sync()); |
| |
| return ChildThreadImpl::Send(msg); |
| } |
| |
| bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg) |
| IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize) |
| IPC_MESSAGE_HANDLER(GpuMsg_Finalize, OnFinalize) |
| IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo) |
| IPC_MESSAGE_HANDLER(GpuMsg_GetVideoMemoryUsageStats, |
| OnGetVideoMemoryUsageStats) |
| IPC_MESSAGE_HANDLER(GpuMsg_Clean, OnClean) |
| IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash) |
| IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang) |
| IPC_MESSAGE_HANDLER(GpuMsg_DisableWatchdog, OnDisableWatchdog) |
| IPC_MESSAGE_HANDLER(GpuMsg_GpuSwitched, OnGpuSwitched) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| |
| if (handled) |
| return true; |
| |
| #if defined(USE_OZONE) |
| if (ui::OzonePlatform::GetInstance() |
| ->GetGpuPlatformSupport() |
| ->OnMessageReceived(msg)) |
| return true; |
| #endif |
| |
| return false; |
| } |
| |
| bool GpuChildThread::OnMessageReceived(const IPC::Message& msg) { |
| if (ChildThreadImpl::OnMessageReceived(msg)) |
| return true; |
| |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg) |
| #if defined(OS_MACOSX) |
| IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented, |
| OnBufferPresented) |
| #endif |
| IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) |
| IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) |
| IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer) |
| IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader) |
| IPC_MESSAGE_HANDLER(GpuMsg_UpdateValueState, OnUpdateValueState) |
| #if defined(OS_ANDROID) |
| IPC_MESSAGE_HANDLER(GpuMsg_WakeUpGpu, OnWakeUpGpu); |
| #endif |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| if (handled) |
| return true; |
| |
| return false; |
| } |
| |
| void GpuChildThread::AddSubscription(int32_t client_id, unsigned int target) { |
| Send(new GpuHostMsg_AddSubscription(client_id, target)); |
| } |
| |
| void GpuChildThread::ChannelEstablished( |
| const IPC::ChannelHandle& channel_handle) { |
| Send(new GpuHostMsg_ChannelEstablished(channel_handle)); |
| } |
| |
| void GpuChildThread::DidCreateOffscreenContext(const GURL& active_url) { |
| Send(new GpuHostMsg_DidCreateOffscreenContext(active_url)); |
| } |
| |
| void GpuChildThread::DidDestroyChannel(int client_id) { |
| Send(new GpuHostMsg_DestroyChannel(client_id)); |
| } |
| |
| void GpuChildThread::DidDestroyOffscreenContext(const GURL& active_url) { |
| Send(new GpuHostMsg_DidDestroyOffscreenContext(active_url)); |
| } |
| |
| void GpuChildThread::DidLoseContext(bool offscreen, |
| gpu::error::ContextLostReason reason, |
| const GURL& active_url) { |
| Send(new GpuHostMsg_DidLoseContext(offscreen, reason, active_url)); |
| } |
| |
| void GpuChildThread::GpuMemoryUmaStats(const GPUMemoryUmaStats& params) { |
| Send(new GpuHostMsg_GpuMemoryUmaStats(params)); |
| } |
| |
| void GpuChildThread::RemoveSubscription(int32_t client_id, |
| unsigned int target) { |
| Send(new GpuHostMsg_RemoveSubscription(client_id, target)); |
| } |
| |
| #if defined(OS_MACOSX) |
| void GpuChildThread::SendAcceleratedSurfaceBuffersSwapped( |
| const AcceleratedSurfaceBuffersSwappedParams& params) { |
| Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); |
| } |
| #endif |
| |
| #if defined(OS_WIN) |
| void GpuChildThread::SendAcceleratedSurfaceCreatedChildWindow( |
| const gfx::PluginWindowHandle& parent_window, |
| const gfx::PluginWindowHandle& child_window) { |
| Send(new GpuHostMsg_AcceleratedSurfaceCreatedChildWindow(parent_window, |
| child_window)); |
| } |
| #endif |
| |
| void GpuChildThread::StoreShaderToDisk(int32_t client_id, |
| const std::string& key, |
| const std::string& shader) { |
| Send(new GpuHostMsg_CacheShader(client_id, key, shader)); |
| } |
| |
| void GpuChildThread::OnInitialize() { |
| // Record initialization only after collecting the GPU info because that can |
| // take a significant amount of time. |
| gpu_info_.initialization_time = base::Time::Now() - process_start_time_; |
| Send(new GpuHostMsg_Initialized(!dead_on_arrival_, gpu_info_)); |
| while (!deferred_messages_.empty()) { |
| Send(deferred_messages_.front()); |
| deferred_messages_.pop(); |
| } |
| |
| if (dead_on_arrival_) { |
| LOG(ERROR) << "Exiting GPU process due to errors during initialization"; |
| base::MessageLoop::current()->QuitWhenIdle(); |
| return; |
| } |
| |
| // We don't need to pipe log messages if we are running the GPU thread in |
| // the browser process. |
| if (!in_browser_process_) |
| logging::SetLogMessageHandler(GpuProcessLogMessageHandler); |
| |
| // Defer creation of the render thread. This is to prevent it from handling |
| // IPC messages before the sandbox has been enabled and all other necessary |
| // initialization has succeeded. |
| gpu_channel_manager_.reset( |
| new GpuChannelManager(gpu_preferences_, this, watchdog_thread_.get(), |
| base::ThreadTaskRunnerHandle::Get().get(), |
| ChildProcess::current()->io_task_runner(), |
| ChildProcess::current()->GetShutDownEvent(), |
| sync_point_manager_, gpu_memory_buffer_factory_)); |
| |
| #if defined(USE_OZONE) |
| ui::OzonePlatform::GetInstance() |
| ->GetGpuPlatformSupport() |
| ->OnChannelEstablished(this); |
| #endif |
| } |
| |
| void GpuChildThread::OnFinalize() { |
| // Quit the GPU process |
| base::MessageLoop::current()->QuitWhenIdle(); |
| } |
| |
| void GpuChildThread::StopWatchdog() { |
| if (watchdog_thread_.get()) { |
| watchdog_thread_->Stop(); |
| } |
| } |
| |
| // static |
| gpu::GpuPreferences GpuChildThread::GetGpuPreferencesFromCommandLine() { |
| // TODO(penghuang): share below code with |
| // android_webview/browser/deferred_gpu_command_service.cc |
| // http://crbug.com/590825 |
| // For any modification of below code, deferred_gpu_command_service.cc should |
| // be updated as well. |
| DCHECK(base::CommandLine::InitializedForCurrentProcess()); |
| const base::CommandLine* command_line = |
| base::CommandLine::ForCurrentProcess(); |
| gpu::GpuPreferences gpu_preferences; |
| gpu_preferences.single_process = |
| command_line->HasSwitch(switches::kSingleProcess); |
| gpu_preferences.in_process_gpu = |
| command_line->HasSwitch(switches::kInProcessGPU); |
| gpu_preferences.ui_prioritize_in_gpu_process = |
| command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess); |
| gpu_preferences.compile_shader_always_succeeds = |
| command_line->HasSwitch(switches::kCompileShaderAlwaysSucceeds); |
| gpu_preferences.disable_gl_error_limit = |
| command_line->HasSwitch(switches::kDisableGLErrorLimit); |
| gpu_preferences.disable_glsl_translator = |
| command_line->HasSwitch(switches::kDisableGLSLTranslator); |
| gpu_preferences.disable_gpu_driver_bug_workarounds = |
| command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds); |
| gpu_preferences.disable_shader_name_hashing = |
| command_line->HasSwitch(switches::kDisableShaderNameHashing); |
| gpu_preferences.enable_gpu_command_logging = |
| command_line->HasSwitch(switches::kEnableGPUCommandLogging); |
| gpu_preferences.enable_gpu_debugging = |
| command_line->HasSwitch(switches::kEnableGPUDebugging); |
| gpu_preferences.enable_gpu_service_logging_gpu = |
| command_line->HasSwitch(switches::kEnableGPUServiceLoggingGPU); |
| gpu_preferences.disable_gpu_program_cache = |
| command_line->HasSwitch(switches::kDisableGpuProgramCache); |
| gpu_preferences.enforce_gl_minimums = |
| command_line->HasSwitch(switches::kEnforceGLMinimums); |
| if (GetSizeTFromSwitch(command_line, switches::kForceGpuMemAvailableMb, |
| &gpu_preferences.force_gpu_mem_available)) { |
| gpu_preferences.force_gpu_mem_available *= 1024 * 1024; |
| } |
| if (GetSizeTFromSwitch(command_line, switches::kGpuProgramCacheSizeKb, |
| &gpu_preferences.gpu_program_cache_size)) { |
| gpu_preferences.gpu_program_cache_size *= 1024; |
| } |
| gpu_preferences.enable_share_group_async_texture_upload = |
| command_line->HasSwitch(switches::kEnableShareGroupAsyncTextureUpload); |
| gpu_preferences.enable_subscribe_uniform_extension = |
| command_line->HasSwitch(switches::kEnableSubscribeUniformExtension); |
| gpu_preferences.enable_threaded_texture_mailboxes = |
| command_line->HasSwitch(switches::kEnableThreadedTextureMailboxes); |
| gpu_preferences.gl_shader_interm_output = |
| command_line->HasSwitch(switches::kGLShaderIntermOutput); |
| gpu_preferences.emulate_shader_precision = |
| command_line->HasSwitch(switches::kEmulateShaderPrecision); |
| gpu_preferences.enable_gpu_service_logging = |
| command_line->HasSwitch(switches::kEnableGPUServiceLogging); |
| gpu_preferences.enable_gpu_service_tracing = |
| command_line->HasSwitch(switches::kEnableGPUServiceTracing); |
| gpu_preferences.enable_unsafe_es3_apis = |
| command_line->HasSwitch(switches::kEnableUnsafeES3APIs); |
| return gpu_preferences; |
| } |
| |
| void GpuChildThread::OnCollectGraphicsInfo() { |
| #if defined(OS_WIN) |
| // GPU full info collection should only happen on un-sandboxed GPU process |
| // or single process/in-process gpu mode on Windows. |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| DCHECK(command_line->HasSwitch(switches::kDisableGpuSandbox) || |
| in_browser_process_); |
| #endif // OS_WIN |
| |
| gpu::CollectInfoResult result = |
| gpu::CollectContextGraphicsInfo(&gpu_info_); |
| switch (result) { |
| case gpu::kCollectInfoFatalFailure: |
| LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal)."; |
| // TODO(piman): can we signal overall failure? |
| break; |
| case gpu::kCollectInfoNonFatalFailure: |
| DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; |
| break; |
| case gpu::kCollectInfoNone: |
| NOTREACHED(); |
| break; |
| case gpu::kCollectInfoSuccess: |
| break; |
| } |
| GetContentClient()->SetGpuInfo(gpu_info_); |
| |
| #if defined(OS_WIN) |
| // This is slow, but it's the only thing the unsandboxed GPU process does, |
| // and GpuDataManager prevents us from sending multiple collecting requests, |
| // so it's OK to be blocking. |
| gpu::GetDxDiagnostics(&gpu_info_.dx_diagnostics); |
| gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoSuccess; |
| #endif // OS_WIN |
| |
| Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_)); |
| |
| #if defined(OS_WIN) |
| if (!in_browser_process_) { |
| // The unsandboxed GPU process fulfilled its duty. Rest in peace. |
| base::MessageLoop::current()->QuitWhenIdle(); |
| } |
| #endif // OS_WIN |
| } |
| |
| void GpuChildThread::OnGetVideoMemoryUsageStats() { |
| GPUVideoMemoryUsageStats video_memory_usage_stats; |
| if (gpu_channel_manager_) { |
| gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats( |
| &video_memory_usage_stats); |
| } |
| Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats)); |
| } |
| |
| void GpuChildThread::OnClean() { |
| DVLOG(1) << "GPU: Removing all contexts"; |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->DestroyAllChannels(); |
| } |
| |
| void GpuChildThread::OnCrash() { |
| DVLOG(1) << "GPU: Simulating GPU crash"; |
| // Good bye, cruel world. |
| volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL; |
| *it_s_the_end_of_the_world_as_we_know_it = 0xdead; |
| } |
| |
| void GpuChildThread::OnHang() { |
| DVLOG(1) << "GPU: Simulating GPU hang"; |
| for (;;) { |
| // Do not sleep here. The GPU watchdog timer tracks the amount of user |
| // time this thread is using and it doesn't use much while calling Sleep. |
| } |
| } |
| |
| void GpuChildThread::OnDisableWatchdog() { |
| DVLOG(1) << "GPU: Disabling watchdog thread"; |
| if (watchdog_thread_.get()) { |
| // Disarm the watchdog before shutting down the message loop. This prevents |
| // the future posting of tasks to the message loop. |
| if (watchdog_thread_->message_loop()) |
| watchdog_thread_->PostAcknowledge(); |
| // Prevent rearming. |
| watchdog_thread_->Stop(); |
| } |
| } |
| |
| void GpuChildThread::OnGpuSwitched() { |
| DVLOG(1) << "GPU: GPU has switched"; |
| // Notify observers in the GPU process. |
| ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched(); |
| } |
| |
| #if defined(OS_MACOSX) |
| void GpuChildThread::OnBufferPresented(const BufferPresentedParams& params) { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->BufferPresented(params); |
| } |
| #endif |
| |
| void GpuChildThread::OnEstablishChannel(const EstablishChannelParams& params) { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->EstablishChannel(params); |
| } |
| |
| void GpuChildThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->CloseChannel(channel_handle); |
| } |
| |
| void GpuChildThread::OnLoadedShader(const std::string& shader) { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->PopulateShaderCache(shader); |
| } |
| |
| void GpuChildThread::OnDestroyGpuMemoryBuffer( |
| gfx::GpuMemoryBufferId id, |
| int client_id, |
| const gpu::SyncToken& sync_token) { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->DestroyGpuMemoryBuffer(id, client_id, sync_token); |
| } |
| |
| void GpuChildThread::OnUpdateValueState(int client_id, |
| unsigned int target, |
| const gpu::ValueState& state) { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->UpdateValueState(client_id, target, state); |
| } |
| |
| #if defined(OS_ANDROID) |
| void GpuChildThread::OnWakeUpGpu() { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->WakeUpGpu(); |
| } |
| #endif |
| |
| void GpuChildThread::OnLoseAllContexts() { |
| if (gpu_channel_manager_) |
| gpu_channel_manager_->DestroyAllChannels(); |
| } |
| |
| void GpuChildThread::BindProcessControlRequest( |
| mojo::InterfaceRequest<ProcessControl> request) { |
| DVLOG(1) << "GPU: Binding ProcessControl request"; |
| DCHECK(process_control_); |
| process_control_bindings_.AddBinding(process_control_.get(), |
| std::move(request)); |
| } |
| |
| } // namespace content |