diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-06-18 14:10:49 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-06-18 13:53:24 +0000 |
commit | 813fbf95af77a531c57a8c497345ad2c61d475b3 (patch) | |
tree | 821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/content/gpu | |
parent | af6588f8d723931a298c995fa97259bb7f7deb55 (diff) | |
download | qtwebengine-chromium-813fbf95af77a531c57a8c497345ad2c61d475b3.tar.gz |
BASELINE: Update chromium to 44.0.2403.47
Change-Id: Ie056fedba95cf5e5c76b30c4b2c80fca4764aa2f
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/content/gpu')
-rw-r--r-- | chromium/content/gpu/BUILD.gn | 26 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_child_thread.cc | 53 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_child_thread.h | 7 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_main.cc | 95 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_watchdog_thread.cc | 93 | ||||
-rw-r--r-- | chromium/content/gpu/gpu_watchdog_thread.h | 23 | ||||
-rw-r--r-- | chromium/content/gpu/in_process_gpu_thread.cc | 11 | ||||
-rw-r--r-- | chromium/content/gpu/in_process_gpu_thread.h | 9 |
8 files changed, 230 insertions, 87 deletions
diff --git a/chromium/content/gpu/BUILD.gn b/chromium/content/gpu/BUILD.gn index d1f844897d8..2f5d1133244 100644 --- a/chromium/content/gpu/BUILD.gn +++ b/chromium/content/gpu/BUILD.gn @@ -5,15 +5,30 @@ import("//build/config/ui.gni") import("//content/content.gni") -source_set("gpu") { +# See //content/BUILD.gn for how this works. +group("gpu") { + visibility = [ "//content/*" ] + + if (is_component_build) { + public_deps = [ + "//content", + ] + } else { + public_deps = [ + ":gpu_sources", + ] + } +} + +source_set("gpu_sources") { visibility = [ "//content/*" ] sources = [ + "gpu_child_thread.cc", + "gpu_child_thread.h", "gpu_main.cc", "gpu_process.cc", "gpu_process.h", - "gpu_child_thread.cc", - "gpu_child_thread.h", "gpu_watchdog_thread.cc", "gpu_watchdog_thread.h", "in_process_gpu_thread.cc", @@ -25,7 +40,8 @@ source_set("gpu") { deps = [ "//base", "//content:export", - "//mojo/public/interfaces/application", + "//content/public/child:child_sources", + "//mojo/application/public/interfaces", "//skia", "//ui/gl", ] @@ -42,7 +58,7 @@ source_set("gpu") { ] } - if (is_chromeos && cpu_arch != "arm") { + if (is_chromeos && current_cpu != "arm") { configs += [ "//third_party/libva:libva_config" ] } diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc index f47294b9d66..3d26c84e876 100644 --- a/chromium/content/gpu/gpu_child_thread.cc +++ b/chromium/content/gpu/gpu_child_thread.cc @@ -44,13 +44,28 @@ bool GpuProcessLogMessageHandler(int severity, return false; } +ChildThreadImpl::Options GetOptions() { + ChildThreadImpl::Options::Builder builder; + +#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) - : dead_on_arrival_(dead_on_arrival), + : ChildThreadImpl(GetOptions()), + dead_on_arrival_(dead_on_arrival), gpu_info_(gpu_info), deferred_messages_(deferred_messages), in_browser_process_(false) { @@ -61,16 +76,19 @@ GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread, g_thread_safe_sender.Get() = thread_safe_sender(); } -GpuChildThread::GpuChildThread(const std::string& channel_id) - : ChildThread(Options(channel_id, false)), +GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params) + : ChildThreadImpl(ChildThreadImpl::Options::Builder() + .InBrowserProcess(params) + .Build()), dead_on_arrival_(false), in_browser_process_(true) { #if defined(OS_WIN) target_services_ = NULL; #endif - DCHECK( - CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) || - CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)); + DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSingleProcess) || + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kInProcessGPU)); #if !defined(OS_ANDROID) // For single process and in-process GPU mode, we need to load and // initialize the GL implementation and locate the GL entry points here. @@ -86,7 +104,7 @@ GpuChildThread::~GpuChildThread() { } void GpuChildThread::Shutdown() { - ChildThread::Shutdown(); + ChildThreadImpl::Shutdown(); logging::SetLogMessageHandler(NULL); } @@ -99,7 +117,7 @@ bool GpuChildThread::Send(IPC::Message* msg) { // process. This could result in deadlock. DCHECK(!msg->is_sync()); - return ChildThread::Send(msg); + return ChildThreadImpl::Send(msg); } bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) { @@ -148,9 +166,8 @@ void GpuChildThread::OnInitialize() { } #if defined(OS_ANDROID) - base::PlatformThread::SetThreadPriority( - base::PlatformThread::CurrentHandle(), - base::kThreadPriority_Display); + base::PlatformThread::SetThreadPriority(base::PlatformThread::CurrentHandle(), + base::ThreadPriority::DISPLAY); #endif // We don't need to pipe log messages if we are running the GPU thread in @@ -185,7 +202,7 @@ 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. - CommandLine* command_line = CommandLine::ForCurrentProcess(); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); DCHECK(command_line->HasSwitch(switches::kDisableGpuSandbox) || in_browser_process_); #endif // OS_WIN @@ -198,7 +215,7 @@ void GpuChildThread::OnCollectGraphicsInfo() { // TODO(piman): can we signal overall failure? break; case gpu::kCollectInfoNonFatalFailure: - VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; + DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; break; case gpu::kCollectInfoNone: NOTREACHED(); @@ -235,20 +252,20 @@ void GpuChildThread::OnGetVideoMemoryUsageStats() { } void GpuChildThread::OnClean() { - VLOG(1) << "GPU: Removing all contexts"; + DVLOG(1) << "GPU: Removing all contexts"; if (gpu_channel_manager_) gpu_channel_manager_->LoseAllContexts(); } void GpuChildThread::OnCrash() { - VLOG(1) << "GPU: Simulating GPU crash"; + 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() { - VLOG(1) << "GPU: Simulating GPU hang"; + 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. @@ -256,7 +273,7 @@ void GpuChildThread::OnHang() { } void GpuChildThread::OnDisableWatchdog() { - VLOG(1) << "GPU: Disabling watchdog thread"; + 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. @@ -268,7 +285,7 @@ void GpuChildThread::OnDisableWatchdog() { } void GpuChildThread::OnGpuSwitched() { - VLOG(1) << "GPU: GPU has switched"; + DVLOG(1) << "GPU: GPU has switched"; // Notify observers in the GPU process. ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched(); } diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h index b5c312db935..70a6bb8c13a 100644 --- a/chromium/content/gpu/gpu_child_thread.h +++ b/chromium/content/gpu/gpu_child_thread.h @@ -14,7 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "build/build_config.h" -#include "content/child/child_thread.h" +#include "content/child/child_thread_impl.h" #include "content/common/gpu/gpu_channel.h" #include "content/common/gpu/gpu_channel_manager.h" #include "content/common/gpu/gpu_config.h" @@ -33,7 +33,7 @@ class GpuWatchdogThread; // these per process. It does process initialization and shutdown. It forwards // IPC messages to GpuChannelManager, which is responsible for issuing rendering // commands to the GPU. -class GpuChildThread : public ChildThread { +class GpuChildThread : public ChildThreadImpl { public: typedef std::queue<IPC::Message*> DeferredMessages; @@ -42,8 +42,7 @@ class GpuChildThread : public ChildThread { const gpu::GPUInfo& gpu_info, const DeferredMessages& deferred_messages); - // For single-process mode. - explicit GpuChildThread(const std::string& channel_id); + explicit GpuChildThread(const InProcessChildThreadParams& params); ~GpuChildThread() override; diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc index 37606e2b3d8..c6a59fc9c19 100644 --- a/chromium/content/gpu/gpu_main.cc +++ b/chromium/content/gpu/gpu_main.cc @@ -9,20 +9,22 @@ #include <windows.h> #endif -#include "base/debug/trace_event.h" -#include "base/environment.h" #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" +#include "base/metrics/statistics_recorder.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" +#include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/platform_thread.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "content/child/child_process.h" #include "content/common/content_constants_internal.h" #include "content/common/gpu/gpu_config.h" #include "content/common/gpu/gpu_messages.h" +#include "content/common/gpu/media/gpu_video_decode_accelerator.h" #include "content/common/gpu/media/gpu_video_encode_accelerator.h" #include "content/common/sandbox_linux/sandbox_linux.h" #include "content/gpu/gpu_child_thread.h" @@ -33,6 +35,7 @@ #include "content/public/common/main_function_params.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 "ui/events/platform/platform_event_source.h" #include "ui/gl/gl_implementation.h" @@ -59,8 +62,13 @@ #include "content/common/sandbox_mac.h" #endif -#if defined(ADDRESS_SANITIZER) -#include <sanitizer/asan_interface.h> +#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) +#include "content/common/gpu/media/vaapi_wrapper.h" +#endif + +#if defined(SANITIZER_COVERAGE) +#include <sanitizer/common_interface_defs.h> +#include <sanitizer/coverage_interface.h> #endif const int kGpuTimeout = 10000; @@ -70,8 +78,8 @@ namespace content { namespace { void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, - const CommandLine& command_line); -bool WarmUpSandbox(const CommandLine& command_line); + const base::CommandLine& command_line); +bool WarmUpSandbox(const base::CommandLine& command_line); #if !defined(OS_MACOSX) bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info); @@ -105,11 +113,11 @@ bool GpuProcessLogMessageHandler(int severity, // Main function for starting the Gpu process. int GpuMain(const MainFunctionParams& parameters) { TRACE_EVENT0("gpu", "GpuMain"); - base::debug::TraceLog::GetInstance()->SetProcessName("GPU Process"); - base::debug::TraceLog::GetInstance()->SetProcessSortIndex( + base::trace_event::TraceLog::GetInstance()->SetProcessName("GPU Process"); + base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( kTraceEventGpuProcessSortIndex); - const CommandLine& command_line = parameters.command_line; + const base::CommandLine& command_line = parameters.command_line; if (command_line.HasSwitch(switches::kGpuStartupDialog)) { ChildProcess::WaitForDebugger("Gpu"); } @@ -152,16 +160,9 @@ int GpuMain(const MainFunctionParams& parameters) { bool dead_on_arrival = false; #if defined(OS_WIN) - base::MessageLoop::Type message_loop_type = base::MessageLoop::TYPE_IO; - // Unless we're running on desktop GL, we don't need a UI message - // loop, so avoid its use to work around apparent problems with some - // third-party software. - if (command_line.HasSwitch(switches::kUseGL) && - command_line.GetSwitchValueASCII(switches::kUseGL) == - gfx::kGLImplementationDesktopName) { - message_loop_type = base::MessageLoop::TYPE_UI; - } - base::MessageLoop main_message_loop(message_loop_type); + // Use a UI message loop because ANGLE and the desktop GL platform can + // create child windows to render to. + base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); #elif defined(OS_LINUX) && defined(USE_X11) // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX // and https://crbug.com/326995. @@ -213,23 +214,17 @@ int GpuMain(const MainFunctionParams& parameters) { watchdog_thread->StartWithOptions(options); } - // Temporarily disable DRI3 on desktop Linux. - // The GPU process is crashing on DRI3-enabled desktop Linux systems. - // TODO(jorgelo): remove this when crbug.com/415681 is fixed. -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) - { - scoped_ptr<base::Environment> env(base::Environment::Create()); - env->SetVar("LIBGL_DRI3_DISABLE", "1"); - } -#endif + // Initializes StatisticsRecorder which tracks UMA histograms. + base::StatisticsRecorder::Initialize(); gpu::GPUInfo gpu_info; // Get vendor_id, device_id, driver_version from browser process through // commandline switches. GetGpuInfoFromCommandLine(gpu_info, command_line); - base::TimeDelta collect_context_time; - base::TimeDelta initialize_one_off_time; +#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) + VaapiWrapper::PreSandboxInitialization(); +#endif // Warm up resources that don't need access to GPUInfo. if (WarmUpSandbox(command_line)) { @@ -288,7 +283,7 @@ int GpuMain(const MainFunctionParams& parameters) { // on systems where vendor_id/device_id aren't available. if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { gpu::ApplyGpuDriverBugWorkarounds( - gpu_info, const_cast<CommandLine*>(&command_line)); + gpu_info, const_cast<base::CommandLine*>(&command_line)); } #endif @@ -302,15 +297,19 @@ int GpuMain(const MainFunctionParams& parameters) { #endif // !defined(OS_CHROMEOS) #endif // defined(OS_LINUX) #endif // !defined(OS_MACOSX) - collect_context_time = + base::TimeDelta collect_context_time = base::TimeTicks::Now() - before_collect_context_graphics_info; + UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", + collect_context_time); } else { // gl_initialized VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; dead_on_arrival = true; } - initialize_one_off_time = + base::TimeDelta initialize_one_off_time = base::TimeTicks::Now() - before_initialize_one_off; + UMA_HISTOGRAM_MEDIUM_TIMES("GPU.InitializeOneOffMediumTime", + initialize_one_off_time); if (enable_watchdog && delayed_watchdog_enable) { watchdog_thread = new GpuWatchdogThread(kGpuTimeout); @@ -341,6 +340,8 @@ int GpuMain(const MainFunctionParams& parameters) { gpu_info.sandboxed = Sandbox::SandboxIsCurrentlyActive(); #endif + gpu_info.video_decode_accelerator_supported_profiles = + content::GpuVideoDecodeAccelerator::GetSupportedProfiles(); gpu_info.video_encode_accelerator_supported_profiles = content::GpuVideoEncodeAccelerator::GetSupportedProfiles(); } else { @@ -351,11 +352,6 @@ int GpuMain(const MainFunctionParams& parameters) { GpuProcess gpu_process; - // These UMA must be stored after GpuProcess is constructed as it - // initializes StatisticsRecorder which tracks the histograms. - UMA_HISTOGRAM_TIMES("GPU.CollectContextGraphicsInfo", collect_context_time); - UMA_HISTOGRAM_TIMES("GPU.InitializeOneOffTime", initialize_one_off_time); - GpuChildThread* child_thread = new GpuChildThread(watchdog_thread.get(), dead_on_arrival, gpu_info, @@ -383,7 +379,7 @@ int GpuMain(const MainFunctionParams& parameters) { namespace { void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, - const CommandLine& command_line) { + const base::CommandLine& command_line) { DCHECK(command_line.HasSwitch(switches::kGpuVendorID) && command_line.HasSwitch(switches::kGpuDeviceID) && command_line.HasSwitch(switches::kGpuDriverVersion)); @@ -402,7 +398,7 @@ void GetGpuInfoFromCommandLine(gpu::GPUInfo& gpu_info, GetContentClient()->SetGpuInfo(gpu_info); } -bool WarmUpSandbox(const CommandLine& command_line) { +bool WarmUpSandbox(const base::CommandLine& command_line) { { TRACE_EVENT0("gpu", "Warm up rand"); // Warm up the random subsystem, which needs to be done pre-sandbox on all @@ -422,7 +418,7 @@ bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) { res = false; break; case gpu::kCollectInfoNonFatalFailure: - VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; + DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal)."; break; case gpu::kCollectInfoNone: NOTREACHED(); @@ -441,7 +437,7 @@ bool CanAccessNvidiaDeviceFile() { bool res = true; base::ThreadRestrictions::AssertIOAllowed(); if (access("/dev/nvidiactl", R_OK) != 0) { - VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; + DVLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; res = false; } return res; @@ -452,7 +448,7 @@ void CreateDummyGlContext() { scoped_refptr<gfx::GLSurface> surface( gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size())); if (!surface.get()) { - VLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed"; + DVLOG(1) << "gfx::GLSurface::CreateOffscreenGLSurface failed"; return; } @@ -461,7 +457,7 @@ void CreateDummyGlContext() { scoped_refptr<gfx::GLContext> context(gfx::GLContext::CreateGLContext( NULL, surface.get(), gfx::PreferDiscreteGpu)); if (!context.get()) { - VLOG(1) << "gfx::GLContext::CreateGLContext failed"; + DVLOG(1) << "gfx::GLContext::CreateGLContext failed"; return; } @@ -469,7 +465,7 @@ void CreateDummyGlContext() { if (context->MakeCurrent(surface.get())) { context->ReleaseCurrent(surface.get()); } else { - VLOG(1) << "gfx::GLContext::MakeCurrent failed"; + DVLOG(1) << "gfx::GLContext::MakeCurrent failed"; } } @@ -500,7 +496,7 @@ bool StartSandboxLinux(const gpu::GPUInfo& gpu_info, LinuxSandbox::StopThread(watchdog_thread); } -#if defined(ADDRESS_SANITIZER) +#if defined(SANITIZER_COVERAGE) const std::string sancov_file_name = "gpu." + base::Uint64ToString(base::RandUint64()); LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); @@ -532,6 +528,13 @@ bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) { // content. sandbox::TargetServices* target_services = sandbox_info->target_services; if (target_services) { +#if defined(ADDRESS_SANITIZER) + // Bind and leak dbghelp.dll before the token is lowered, otherwise + // AddressSanitizer will crash when trying to symbolize a report. + if (!LoadLibraryA("dbghelp.dll")) + return false; +#endif + target_services->LowerToken(); return true; } diff --git a/chromium/content/gpu/gpu_watchdog_thread.cc b/chromium/content/gpu/gpu_watchdog_thread.cc index 02b6bff8040..6052d41647d 100644 --- a/chromium/content/gpu/gpu_watchdog_thread.cc +++ b/chromium/content/gpu/gpu_watchdog_thread.cc @@ -21,11 +21,13 @@ namespace content { namespace { -const int64 kCheckPeriodMs = 2000; #if defined(OS_CHROMEOS) const base::FilePath::CharType kTtyFilePath[] = FILE_PATH_LITERAL("/sys/class/tty/tty0/active"); #endif +#if defined(USE_X11) +const unsigned char text[20] = "check"; +#endif } // namespace GpuWatchdogThread::GpuWatchdogThread(int timeout) @@ -39,6 +41,11 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout) #endif task_observer_(this), suspended_(false), +#if defined(USE_X11) + display_(NULL), + window_(0), + atom_(None), +#endif weak_factory_(this) { DCHECK(timeout >= 0); @@ -59,6 +66,9 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout) #if defined(OS_CHROMEOS) tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r"); #endif +#if defined(USE_X11) + SetupXServer(); +#endif watched_message_loop_->AddTaskObserver(&task_observer_); } @@ -102,7 +112,6 @@ void GpuWatchdogThread::GpuWatchdogTaskObserver::WillProcessTask( void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask( const base::PendingTask& pending_task) { - watchdog_->CheckArmed(); } GpuWatchdogThread::~GpuWatchdogThread() { @@ -123,6 +132,11 @@ GpuWatchdogThread::~GpuWatchdogThread() { fclose(tty_file_); #endif +#if defined(USE_X11) + XDestroyWindow(display_, window_); + XCloseDisplay(display_); +#endif + watched_message_loop_->RemoveTaskObserver(&task_observer_); } @@ -152,7 +166,7 @@ void GpuWatchdogThread::OnAcknowledge() { FROM_HERE, base::Bind(&GpuWatchdogThread::OnCheck, weak_factory_.GetWeakPtr(), was_suspended), - base::TimeDelta::FromMilliseconds(kCheckPeriodMs)); + 0.5 * timeout_); } void GpuWatchdogThread::OnCheck(bool after_suspend) { @@ -188,9 +202,8 @@ void GpuWatchdogThread::OnCheck(bool after_suspend) { // not respond in time. message_loop()->PostDelayedTask( FROM_HERE, - base::Bind( - &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, - weak_factory_.GetWeakPtr()), + base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, + weak_factory_.GetWeakPtr()), timeout); } @@ -224,6 +237,52 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { return; } +#if defined(USE_X11) + XWindowAttributes attributes; + XGetWindowAttributes(display_, window_, &attributes); + + XSelectInput(display_, window_, PropertyChangeMask); + SetupXChangeProp(); + + XFlush(display_); + + // We wait for the property change event with a timeout. If it arrives we know + // that X is responsive and is not the cause of the watchdog trigger, so we + // should + // terminate. If it times out, it may be due to X taking a long time, but + // terminating won't help, so ignore the watchdog trigger. + XEvent event_return; + base::TimeTicks deadline = base::TimeTicks::Now() + timeout_; + while (true) { + base::TimeDelta delta = deadline - base::TimeTicks::Now(); + if (delta < base::TimeDelta()) { + return; + } else { + while (XCheckWindowEvent(display_, window_, PropertyChangeMask, + &event_return)) { + if (MatchXEventAtom(&event_return)) + break; + } + struct pollfd fds[1]; + fds[0].fd = XConnectionNumber(display_); + fds[0].events = POLLIN; + int status = poll(fds, 1, delta.InMilliseconds()); + if (status == -1) { + if (errno == EINTR) { + continue; + } else { + LOG(FATAL) << "Lost X connection, aborting."; + break; + } + } else if (status == 0) { + return; + } else { + continue; + } + } + } +#endif + // For minimal developer annoyance, don't keep terminating. You need to skip // the call to base::Process::Terminate below in a debugger for this to be // useful. @@ -259,6 +318,28 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { terminated = true; } +#if defined(USE_X11) +void GpuWatchdogThread::SetupXServer() { + display_ = XOpenDisplay(NULL); + window_ = XCreateWindow(display_, DefaultRootWindow(display_), 0, 0, 1, 1, 0, + CopyFromParent, InputOutput, CopyFromParent, 0, NULL); + atom_ = XInternAtom(display_, "CHECK", False); +} + +void GpuWatchdogThread::SetupXChangeProp() { + XChangeProperty(display_, window_, atom_, XA_STRING, 8, PropModeReplace, text, + (arraysize(text) - 1)); +} + +bool GpuWatchdogThread::MatchXEventAtom(XEvent* event) { + if (event->xproperty.window == window_ && event->type == PropertyNotify && + event->xproperty.atom == atom_) + return true; + + return false; +} + +#endif void GpuWatchdogThread::AddPowerObserver() { message_loop()->PostTask( FROM_HERE, diff --git a/chromium/content/gpu/gpu_watchdog_thread.h b/chromium/content/gpu/gpu_watchdog_thread.h index c766ca34937..9dd184ab326 100644 --- a/chromium/content/gpu/gpu_watchdog_thread.h +++ b/chromium/content/gpu/gpu_watchdog_thread.h @@ -12,6 +12,18 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "content/common/gpu/gpu_watchdog.h" +#include "ui/gfx/native_widget_types.h" + +#if defined(USE_X11) +extern "C" { +#include <X11/Xlib.h> +#include <X11/Xatom.h> +} +#include <sys/poll.h> +#include "ui/base/x/x11_util.h" +#include "ui/gfx/x/x11_types.h" + +#endif namespace content { @@ -62,6 +74,11 @@ class GpuWatchdogThread : public base::Thread, void OnAcknowledge(); void OnCheck(bool after_suspend); void DeliberatelyTerminateToRecoverFromHang(); +#if defined(USE_X11) + void SetupXServer(); + void SetupXChangeProp(); + bool MatchXEventAtom(XEvent* event); +#endif void OnAddPowerObserver(); @@ -93,6 +110,12 @@ class GpuWatchdogThread : public base::Thread, FILE* tty_file_; #endif +#if defined(USE_X11) + XDisplay* display_; + gfx::AcceleratedWidget window_; + XAtom atom_; +#endif + base::WeakPtrFactory<GpuWatchdogThread> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GpuWatchdogThread); diff --git a/chromium/content/gpu/in_process_gpu_thread.cc b/chromium/content/gpu/in_process_gpu_thread.cc index 8a7818d6e19..dfd9d358e5f 100644 --- a/chromium/content/gpu/in_process_gpu_thread.cc +++ b/chromium/content/gpu/in_process_gpu_thread.cc @@ -9,9 +9,9 @@ namespace content { -InProcessGpuThread::InProcessGpuThread(const std::string& channel_id) +InProcessGpuThread::InProcessGpuThread(const InProcessChildThreadParams& params) : base::Thread("Chrome_InProcGpuThread"), - channel_id_(channel_id), + params_(params), gpu_process_(NULL) { } @@ -23,7 +23,7 @@ void InProcessGpuThread::Init() { gpu_process_ = new GpuProcess(); // The process object takes ownership of the thread object, so do not // save and delete the pointer. - gpu_process_->set_main_thread(new GpuChildThread(channel_id_)); + gpu_process_->set_main_thread(new GpuChildThread(params_)); } void InProcessGpuThread::CleanUp() { @@ -31,8 +31,9 @@ void InProcessGpuThread::CleanUp() { delete gpu_process_; } -base::Thread* CreateInProcessGpuThread(const std::string& channel_id) { - return new InProcessGpuThread(channel_id); +base::Thread* CreateInProcessGpuThread( + const InProcessChildThreadParams& params) { + return new InProcessGpuThread(params); } } // namespace content diff --git a/chromium/content/gpu/in_process_gpu_thread.h b/chromium/content/gpu/in_process_gpu_thread.h index e8e0140dc28..67ba017c54d 100644 --- a/chromium/content/gpu/in_process_gpu_thread.h +++ b/chromium/content/gpu/in_process_gpu_thread.h @@ -7,6 +7,8 @@ #include "base/threading/thread.h" #include "content/common/content_export.h" +#include "content/common/content_export.h" +#include "content/common/in_process_child_thread_params.h" namespace content { @@ -16,7 +18,7 @@ class GpuProcess; // with --in-process-gpu or --single-process. class InProcessGpuThread : public base::Thread { public: - explicit InProcessGpuThread(const std::string& channel_id); + InProcessGpuThread(const InProcessChildThreadParams& params); ~InProcessGpuThread() override; protected: @@ -24,7 +26,8 @@ class InProcessGpuThread : public base::Thread { void CleanUp() override; private: - std::string channel_id_; + InProcessChildThreadParams params_; + // Deleted in CleanUp() on the gpu thread, so don't use smart pointers. GpuProcess* gpu_process_; @@ -32,7 +35,7 @@ class InProcessGpuThread : public base::Thread { }; CONTENT_EXPORT base::Thread* CreateInProcessGpuThread( - const std::string& channel_id); + const InProcessChildThreadParams& params); } // namespace content |