summaryrefslogtreecommitdiff
path: root/chromium/content/gpu
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-06-18 14:10:49 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2015-06-18 13:53:24 +0000
commit813fbf95af77a531c57a8c497345ad2c61d475b3 (patch)
tree821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/content/gpu
parentaf6588f8d723931a298c995fa97259bb7f7deb55 (diff)
downloadqtwebengine-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.gn26
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc53
-rw-r--r--chromium/content/gpu/gpu_child_thread.h7
-rw-r--r--chromium/content/gpu/gpu_main.cc95
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.cc93
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.h23
-rw-r--r--chromium/content/gpu/in_process_gpu_thread.cc11
-rw-r--r--chromium/content/gpu/in_process_gpu_thread.h9
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