Skip to content

Commit

Permalink
Blacklist GLX indirect rendering
Browse files Browse the repository at this point in the history
Several part to this CL:
1- Implement gathering the direct rendering information. It needs a context, so
it is done through the CollectGraphicsInfoGL hook
2- Implement logic to hook the information to the blacklist
3- In some cases, indirect rendering causes creating surfaces/contexts, needed
to collect the info, to fail. So expose the failure mode (fatal vs non-fatal) to
the caller so that we can fully fail GPU things in that case.

BUG=72373,339244

Review URL: https://codereview.chromium.org/194303002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258721 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
piman@chromium.org committed Mar 22, 2014
1 parent f9942c2 commit 0e8cac7
Show file tree
Hide file tree
Showing 22 changed files with 180 additions and 66 deletions.
4 changes: 4 additions & 0 deletions content/browser/gpu/gpu_internals_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
gpu_info.gl_ws_version));
basic_info->Append(NewDescriptionValuePair("Window system binding extensions",
gpu_info.gl_ws_extensions));
std::string direct_rendering = gpu_info.direct_rendering ? "Yes" : "No";
basic_info->Append(
NewDescriptionValuePair("Direct rendering", direct_rendering));

std::string reset_strategy =
base::StringPrintf("0x%04x", gpu_info.gl_reset_notification_strategy);
basic_info->Append(NewDescriptionValuePair(
Expand Down
2 changes: 2 additions & 0 deletions content/browser/gpu/gpu_process_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,8 @@ void GpuProcessHost::OnInitialized(bool result, const gpu::GPUInfo& gpu_info) {

if (!initialized_)
GpuDataManagerImpl::GetInstance()->OnGpuProcessInitFailure();
else if (!in_process_)
GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
}

void GpuProcessHost::OnChannelEstablished(
Expand Down
1 change: 1 addition & 0 deletions content/common/gpu/gpu_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo)
IPC_STRUCT_TRAITS_MEMBER(can_lose_context)
IPC_STRUCT_TRAITS_MEMBER(performance_stats)
IPC_STRUCT_TRAITS_MEMBER(software_rendering)
IPC_STRUCT_TRAITS_MEMBER(direct_rendering)
IPC_STRUCT_TRAITS_MEMBER(sandboxed)
#if defined(OS_WIN)
IPC_STRUCT_TRAITS_MEMBER(dx_diagnostics)
Expand Down
27 changes: 16 additions & 11 deletions content/gpu/gpu_child_thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
}

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());
Expand All @@ -142,10 +145,6 @@ void GpuChildThread::OnInitialize() {
if (!in_browser_process_)
logging::SetLogMessageHandler(GpuProcessLogMessageHandler);

// 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_;

// 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.
Expand All @@ -154,11 +153,6 @@ void GpuChildThread::OnInitialize() {
watchdog_thread_.get(),
ChildProcess::current()->io_message_loop_proxy(),
ChildProcess::current()->GetShutDownEvent()));

// Ensure the browser process receives the GPU info before a reply to any
// subsequent IPC it might send.
if (!in_browser_process_)
Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
}

void GpuChildThread::StopWatchdog() {
Expand All @@ -176,8 +170,19 @@ void GpuChildThread::OnCollectGraphicsInfo() {
in_browser_process_);
#endif // OS_WIN

if (!gpu::CollectContextGraphicsInfo(&gpu_info_))
VLOG(1) << "gpu::CollectGraphicsInfo failed";
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:
VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
break;
case gpu::kCollectInfoSuccess:
break;
}
GetContentClient()->SetGpuInfo(gpu_info_);

#if defined(OS_WIN)
Expand Down
15 changes: 13 additions & 2 deletions content/gpu/gpu_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,19 @@ int GpuMain(const MainFunctionParams& parameters) {
base::TimeTicks before_collect_context_graphics_info =
base::TimeTicks::Now();
#if !defined(OS_MACOSX)
if (!gpu::CollectContextGraphicsInfo(&gpu_info))
VLOG(1) << "gpu::CollectGraphicsInfo failed";
gpu::CollectInfoResult result =
gpu::CollectContextGraphicsInfo(&gpu_info);
switch (result) {
case gpu::kCollectInfoFatalFailure:
LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
dead_on_arrival = true;
break;
case gpu::kCollectInfoNonFatalFailure:
VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
break;
case gpu::kCollectInfoSuccess:
break;
}
GetContentClient()->SetGpuInfo(gpu_info);

#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
Expand Down
19 changes: 19 additions & 0 deletions gpu/config/gpu_control_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,12 @@ bool GpuControlList::IntInfo::IsValid() const {
return op_ != kUnknown;
}

GpuControlList::BoolInfo::BoolInfo(bool value) : value_(value) {}

bool GpuControlList::BoolInfo::Contains(bool value) const {
return value_ == value;
}

// static
GpuControlList::ScopedGpuControlListEntry
GpuControlList::GpuControlListEntry::GetEntryFromValue(
Expand Down Expand Up @@ -744,6 +750,12 @@ GpuControlList::GpuControlListEntry::GetEntryFromValue(
dictionary_entry_count++;
}

bool direct_rendering;
if (value->GetBoolean("direct_rendering", &direct_rendering)) {
entry->SetDirectRenderingInfo(direct_rendering);
dictionary_entry_count++;
}

if (top_level) {
const base::ListValue* feature_value = NULL;
if (value->GetList("features", &feature_value)) {
Expand Down Expand Up @@ -970,6 +982,10 @@ bool GpuControlList::GpuControlListEntry::SetGpuCountInfo(
return gpu_count_info_->IsValid();
}

void GpuControlList::GpuControlListEntry::SetDirectRenderingInfo(bool value) {
direct_rendering_info_.reset(new BoolInfo(value));
}

bool GpuControlList::GpuControlListEntry::SetFeatures(
const std::vector<std::string>& feature_strings,
const FeatureMap& feature_map,
Expand Down Expand Up @@ -1119,6 +1135,9 @@ bool GpuControlList::GpuControlListEntry::Contains(
if (gpu_count_info_.get() != NULL &&
!gpu_count_info_->Contains(gpu_info.secondary_gpus.size() + 1))
return false;
if (direct_rendering_info_.get() != NULL &&
!direct_rendering_info_->Contains(gpu_info.direct_rendering))
return false;
if (cpu_brand_.get() != NULL) {
base::CPU cpu_info;
if (!cpu_brand_->Contains(cpu_info.cpu_brand()))
Expand Down
14 changes: 14 additions & 0 deletions gpu/config/gpu_control_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,17 @@ class GPU_EXPORT GpuControlList {
int value2_;
};

class GPU_EXPORT BoolInfo {
public:
explicit BoolInfo(bool value);

// Determines if a given bool is included in the BoolInfo.
bool Contains(bool value) const;

private:
bool value_;
};

class GPU_EXPORT MachineModelInfo {
public:
MachineModelInfo(const std::string& name_op,
Expand Down Expand Up @@ -413,6 +424,8 @@ class GPU_EXPORT GpuControlList {
const std::string& int_string,
const std::string& int_string2);

void SetDirectRenderingInfo(bool value);

bool SetFeatures(const std::vector<std::string>& features,
const FeatureMap& feature_map,
bool supports_feature_type_all);
Expand Down Expand Up @@ -453,6 +466,7 @@ class GPU_EXPORT GpuControlList {
scoped_ptr<FloatInfo> perf_overall_info_;
scoped_ptr<MachineModelInfo> machine_model_info_;
scoped_ptr<IntInfo> gpu_count_info_;
scoped_ptr<BoolInfo> direct_rendering_info_;
std::set<int> features_;
std::vector<ScopedGpuControlListEntry> exceptions_;
};
Expand Down
2 changes: 2 additions & 0 deletions gpu/config/gpu_control_list_format.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
// 23. "cr_bugs" is an array of associated webkit bug numbers.
// 24. "disabled" is a boolean. If it is present, the entry will be skipped.
// This can not be used in exceptions.
// 25. "direct_rendering" is a boolean. If present, this will filter on whether
// the GL contexts are direct or indirect based on the value.
//
// VERSION includes "op", "style", "value", and "value2". "op" can be any of
// the following values: "=", "<", "<=", ">", ">=", "any", "between". "style"
Expand Down
14 changes: 14 additions & 0 deletions gpu/config/gpu_control_list_number_info_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class NumberInfoTest : public testing::Test {

typedef GpuControlList::FloatInfo FloatInfo;
typedef GpuControlList::IntInfo IntInfo;
typedef GpuControlList::BoolInfo BoolInfo;
};

TEST_F(NumberInfoTest, ValidFloatInfo) {
Expand Down Expand Up @@ -206,5 +207,18 @@ TEST_F(NumberInfoTest, IntComparison) {
}
}

TEST_F(NumberInfoTest, Bool) {
{
BoolInfo info(true);
EXPECT_TRUE(info.Contains(true));
EXPECT_FALSE(info.Contains(false));
}
{
BoolInfo info(false);
EXPECT_FALSE(info.Contains(true));
EXPECT_TRUE(info.Contains(false));
}
}

} // namespace gpu

3 changes: 3 additions & 0 deletions gpu/config/gpu_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ GPUInfo::GPUInfo()
gl_reset_notification_strategy(0),
can_lose_context(false),
software_rendering(false),
direct_rendering(true),
sandboxed(false) {
}

Expand Down Expand Up @@ -70,6 +71,7 @@ void GPUInfo::EnumerateFields(Enumerator* enumerator) const {
bool can_lose_context;
GpuPerformanceStats performance_stats;
bool software_rendering;
bool direct_rendering;
bool sandboxed;
#if defined(OS_WIN)
DxDiagNode dx_diagnostics;
Expand Down Expand Up @@ -121,6 +123,7 @@ void GPUInfo::EnumerateFields(Enumerator* enumerator) const {
enumerator->AddBool("can_lose_context", can_lose_context);
// TODO(kbr): add performance_stats.
enumerator->AddBool("softwareRendering", software_rendering);
enumerator->AddBool("directRendering", direct_rendering);
enumerator->AddBool("sandboxed", sandboxed);
// TODO(kbr): add dx_diagnostics on Windows.
enumerator->EndAuxAttributes();
Expand Down
4 changes: 4 additions & 0 deletions gpu/config/gpu_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ struct GPU_EXPORT GPUInfo {

bool software_rendering;

// Whether the driver uses direct rendering. True on most platforms, false on
// X11 when using remote X.
bool direct_rendering;

// Whether the gpu process is running in a sandbox.
bool sandboxed;

Expand Down
16 changes: 11 additions & 5 deletions gpu/config/gpu_info_collector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,21 @@ std::string GetVersionFromString(const std::string& version_string) {

namespace gpu {

bool CollectGraphicsInfoGL(GPUInfo* gpu_info) {
CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info) {
TRACE_EVENT0("startup", "gpu_info_collector::CollectGraphicsInfoGL");
DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone);

scoped_refptr<gfx::GLSurface> surface(InitializeGLSurface());
if (!surface.get())
return false;
if (!surface.get()) {
LOG(ERROR) << "Could not create surface for info collection.";
return kCollectInfoFatalFailure;
}

scoped_refptr<gfx::GLContext> context(InitializeGLContext(surface.get()));
if (!context.get())
return false;
if (!context.get()) {
LOG(ERROR) << "Could not create context for info collection.";
return kCollectInfoFatalFailure;
}

gpu_info->gl_renderer = GetGLString(GL_RENDERER);
gpu_info->gl_vendor = GetGLString(GL_VENDOR);
Expand All @@ -103,6 +107,7 @@ bool CollectGraphicsInfoGL(GPUInfo* gpu_info) {
gpu_info->gl_ws_vendor = window_system_binding_info.vendor;
gpu_info->gl_ws_version = window_system_binding_info.version;
gpu_info->gl_ws_extensions = window_system_binding_info.extensions;
gpu_info->direct_rendering = window_system_binding_info.direct_rendering;
}

bool supports_robustness =
Expand Down Expand Up @@ -150,6 +155,7 @@ void MergeGPUInfoGL(GPUInfo* basic_gpu_info,

basic_gpu_info->can_lose_context = context_gpu_info.can_lose_context;
basic_gpu_info->sandboxed = context_gpu_info.sandboxed;
basic_gpu_info->direct_rendering = context_gpu_info.direct_rendering;
basic_gpu_info->finalized = context_gpu_info.finalized;
basic_gpu_info->initialization_time = context_gpu_info.initialization_time;
}
Expand Down
21 changes: 16 additions & 5 deletions gpu/config/gpu_info_collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,41 @@ enum GpuIDResult {
kGpuIDNotSupported
};

// Result for the various Collect*Info* functions below.
// Fatal failures are for cases where we can't create a context at all or
// something, making the use of the GPU impossible.
// Non-fatal failures are for cases where we could gather most info, but maybe
// some is missing (e.g. unable to parse a version string or to detect the exact
// model).
enum CollectInfoResult {
kCollectInfoFatalFailure,
kCollectInfoNonFatalFailure,
kCollectInfoSuccess
};

// Collect GPU vendor_id and device ID.
GPU_EXPORT GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id);

// Collects basic GPU info without creating a GL/DirectX context (and without
// the danger of crashing), including vendor_id and device_id.
// This is called at browser process startup time.
// The subset each platform collects may be different.
GPU_EXPORT bool CollectBasicGraphicsInfo(GPUInfo* gpu_info);
GPU_EXPORT CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info);

// Create a GL/DirectX context and collect related info.
// This is called at GPU process startup time.
// Returns true on success.
GPU_EXPORT bool CollectContextGraphicsInfo(GPUInfo* gpu_info);
GPU_EXPORT CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info);

#if defined(OS_WIN)
// Collect the DirectX Disagnostics information about the attached displays.
GPU_EXPORT bool GetDxDiagnostics(DxDiagNode* output);
#endif // OS_WIN

// Create a GL context and collect GL strings and versions.
GPU_EXPORT bool CollectGraphicsInfoGL(GPUInfo* gpu_info);
GPU_EXPORT CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info);

// Each platform stores the driver version on the GL_VERSION string differently
GPU_EXPORT bool CollectDriverInfoGL(GPUInfo* gpu_info);
GPU_EXPORT CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info);

// Merge GPUInfo from CollectContextGraphicsInfo into basic GPUInfo.
// This is platform specific, depending on which info are collected at which
Expand Down
8 changes: 4 additions & 4 deletions gpu/config/gpu_info_collector_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ ScopedRestoreNonOwnedEGLContext::~ScopedRestoreNonOwnedEGLContext() {

namespace gpu {

bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
return CollectBasicGraphicsInfo(gpu_info);
}

Expand All @@ -95,7 +95,7 @@ GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
return kGpuIDNotSupported;
}

bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
gpu_info->can_lose_context = false;
gpu_info->finalized = true;

Expand All @@ -107,12 +107,12 @@ bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
return CollectGraphicsInfoGL(gpu_info);
}

bool CollectDriverInfoGL(GPUInfo* gpu_info) {
CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
gpu_info->driver_version = GetDriverVersionFromString(
gpu_info->gl_version_string);
gpu_info->gpu.vendor_string = gpu_info->gl_vendor;
gpu_info->gpu.device_string = gpu_info->gl_renderer;
return true;
return kCollectInfoSuccess;
}

void MergeGPUInfo(GPUInfo* basic_gpu_info,
Expand Down
Loading

0 comments on commit 0e8cac7

Please sign in to comment.