8000 feat: Implementation of getGPUInfo API. by nitsakh · Pull Request #13486 · electron/electron · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: Implementation of getGPUInfo API. #13486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions atom/browser/api/atom_api_app.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/api/gpuinfo_manager.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/login_handler.h"
Expand Down Expand Up @@ -548,6 +549,7 @@ App::App(v8::Isolate* isolate) {
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
Browser::Get()->AddObserver(this);
content::GpuDataManager::GetInstance()->AddObserver(this);

base::ProcessId pid = base::GetCurrentProcId();
auto process_metric = std::make_unique<atom::ProcessMetric>(
content::PROCESS_TYPE_BROWSER, pid,
Expand Down Expand Up @@ -1148,6 +1150,25 @@ v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) {
return mate::ConvertToV8(isolate, status ? *status : temp);
}

v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate,
const std::string& info_type) {
auto* const gpu_data_manager = content::GpuDataManagerImpl::GetInstance();
scoped_refptr<util::Promise> promise = new util::Promise(isolate);
if ((info_type != "basic" && info_type != "complete") ||
!gpu_data_manager->GpuAccessAllowed(nullptr)) {
promise->Reject("Error fetching GPU Info");
return promise->GetHandle();
}

auto* const info_mgr = GPUInfoManager::GetInstance();
if (info_type == "complete") {
info_mgr->FetchCompleteInfo(promise);
} else /* (info_type == "basic") */ {
info_mgr->FetchBasicInfo(promise);
}
return promise->GetHandle();
}

void App::EnableMixedSandbox(mate::Arguments* args) {
if (Browser::Get()->is_ready()) {
args->ThrowError(
Expand Down Expand Up @@ -1270,6 +1291,7 @@ void App::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getFileIcon", &App::GetFileIcon)
.SetMethod("getAppMetrics", &App::GetAppMetrics)
.SetMethod("getGPUFeatureStatus", &App::GetGPUFeatureStatus)
.SetMethod("getGPUInfo", &App::GetGPUInfo)
// TODO(juturu): Remove in 2.0, deprecate before then with warnings
#if defined(OS_MACOSX)
.SetMethod("moveToApplicationsFolder", &App::MoveToApplicationsFolder)
Expand Down
2 changes: 2 additions & 0 deletions atom/browser/api/atom_api_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ class App : public AtomBrowserClient::Delegate,

std::vector<mate::Dictionary> GetAppMetrics(v8::Isolate* isolate);
v8::Local<v8::Value> GetGPUFeatureStatus(v8::Isolate* isolate);
v8::Local<v8::Promise> GetGPUInfo(v8::Isolate* isolate,
const std::string& info_type);
void EnableMixedSandbox(mate::Arguments* args);

#if defined(OS_MACOSX)
Expand Down
102 changes: 102 additions & 0 deletions atom/browser/api/gpu_info_enumerator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/api/gpu_info_enumerator.h"

#include <utility>

namespace atom {

GPUInfoEnumerator::GPUInfoEnumerator()
: value_stack(), current(std::make_unique<base::DictionaryValue>()) {}

GPUInfoEnumerator::~GPUInfoEnumerator() {}

void GPUInfoEnumerator::AddInt64(const char* name, int64_t value) {
current->SetInteger(name, value);
}

void GPUInfoEnumerator::AddInt(const char* name, int value) {
current->SetInteger(name, value);
}

void GPUInfoEnumerator::AddString(const char* name, const std::string& value) {
if (!value.empty())
current->SetString(name, value);
}

void GPUInfoEnumerator::AddBool(const char* name, bool value) {
current->SetBoolean(name, value);
}

void GPUInfoEnumerator::AddTimeDeltaInSecondsF(const char* name,
const base::TimeDelta& value) {
current->SetInteger(name, value.InMilliseconds());
}

void GPUInfoEnumerator::BeginGPUDevice() {
value_stack.push(std::move(current));
current = std::make_unique<base::DictionaryValue>();
}

void GPUInfoEnumerator::EndGPUDevice() {
auto& top_value = value_stack.top();
// GPUDevice can be more than one. So create a list of all.
// The first one is the active GPU device.
if (top_value->HasKey(kGPUDeviceKey)) {
base::ListValue* list;
top_value->GetList(kGPUDeviceKey, &list);
list->Append(std::move(current));
} else {
auto gpus = std::make_unique<base::ListValue>();
gpus->Append(std::move(current));
top_value->SetList(kGPUDeviceKey, std::move(gpus));
}
current = std::move(top_value);
value_stack.pop();
}

void GPUInfoEnumerator::BeginVideoDecodeAcceleratorSupportedProfile() {
value_stack.push(std::move(current));
current = std::make_unique<base::DictionaryValue>();
}

void GPUInfoEnumerator::EndVideoDecodeAcceleratorSupportedProfile() {
auto& top_value = value_stack.top();
top_value->SetDictionary(kVideoDecodeAcceleratorSupportedProfileKey,
std::move(current));
current = std::move(top_value);
value_stack.pop();
}

void GPUInfoEnumerator::BeginVideoEncodeAcceleratorSupportedProfile() {
value_stack.push(std::move(current));
current = std::make_unique<base::DictionaryValue>();
}

void GPUInfoEnumerator::EndVideoEncodeAcceleratorSupportedProfile() {
auto& top_value = value_stack.top();
top_value->SetDictionary(kVideoEncodeAcceleratorSupportedProfileKey,
std::move(current));
current = std::move(top_value);
value_stack.pop();
}

void GPUInfoEnumerator::BeginAuxAttributes() {
value_stack.push(std::move(current));
current = std::make_unique<base::DictionaryValue>();
}

void GPUInfoEnumerator::EndAuxAttributes() {
auto& top_value = value_stack.top();
top_value->SetDictionary(kAuxAttributesKey, std::move(current));
current = std::move(top_value);
value_stack.pop();
}

std::unique_ptr<base::DictionaryValue> GPUInfoEnumerator::GetDictionary() {
return std::move(current);
}

} // namespace atom
53 changes: 53 additions & 0 deletions atom/browser/api/gpu_info_enumerator.h
6D47
Original file line numberDiff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#ifndef ATOM_BROWSER_API_GPU_INFO_ENUMERATOR_H_
#define ATOM_BROWSER_API_GPU_INFO_ENUMERATOR_H_

#include <memory>
#include <stack>
#include <string>

#include "base/values.h"
#include "gpu/config/gpu_info.h"

namespace atom {

// This class implements the enumerator for reading all the attributes in
// GPUInfo into a dictionary.
class GPUInfoEnumerator final : public gpu::GPUInfo::Enumerator {
const char* kGPUDeviceKey = "gpuDevice";
const char* kVideoDecodeAcceleratorSupportedProfileKey =
"videoDecodeAcceleratorSupportedProfile";
const char* kVideoEncodeAcceleratorSupportedProfileKey =
"videoEncodeAcceleratorSupportedProfile";
const char* kAuxAttributesKey = "auxAttributes";

public:
GPUInfoEnumerator();
~GPUInfoEnumerator() override;
void AddInt64(const char* name, int64_t value) override;
void AddInt(const char* name, int value) override;
void AddString(const char* name, const std::string& value) override;
void AddBool(const char* name, bool value) override;
void AddTimeDeltaInSecondsF(const char* name,
const base::TimeDelta& value) override;
void BeginGPUDevice() override;
void EndGPUDevice() override;
void BeginVideoDecodeAcceleratorSupportedProfile() override;
void EndVideoDecodeAcceleratorSupportedProfile() override;
void BeginVideoEncodeAcceleratorSupportedProfile() override;
void EndVideoEncodeAcceleratorSupportedProfile() override;
void BeginAuxAttributes() override;
void EndAuxAttributes() override;
std::unique_ptr<base::DictionaryValue> GetDictionary();

private:
// The stack is used to manage nested values
std::stack<std::unique_ptr<base::DictionaryValue>> value_stack;
std::unique_ptr<base::DictionaryValue> current;
};

} // namespace atom
#endif // ATOM_BROWSER_API_GPU_INFO_ENUMERATOR_H_
93 changes: 93 additions & 0 deletions atom/browser/api/gpuinfo_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/api/gpuinfo_manager.h"
#include "atom/browser/api/gpu_info_enumerator.h"
#include "base/memory/singleton.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/config/gpu_info_collector.h"

namespace atom {

GPUInfoManager* GPUInfoManager::GetInstance() {
return base::Singleton<GPUInfoManager>::get();
}

GPUInfoManager::GPUInfoManager()
: gpu_data_manager_(content::GpuDataManagerImpl::GetInstance()) {
gpu_data_manager_->AddObserver(this);
}

GPUInfoManager::~GPUInfoManager() {
content::GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
}

// Based on
// https://chromium.googlesource.com/chromium/src.git/+/66.0.3359.181/content/browser/gpu/gpu_data_manager_impl_private.cc#810
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() {
#if defined(OS_MACOSX)
return gpu_data_manager_->GetGPUInfo().gl_vendor.empty();
#elif defined(OS_WIN)
const auto& gpu_info = gpu_data_manager_->GetGPUInfo();
return (gpu_info.dx_diagnostics.values.empty() &&
gpu_info.dx_diagnostics.children.empty());
#else
return false;
#endif
}

// Should be posted to the task runner
void GPUInfoManager::ProcessCompleteInfo() {
const auto result = EnumerateGPUInfo(gpu_data_manager_->GetGPUInfo());
// We have received the complete information, resolve all promises that
// were waiting for this info.
for (const auto& promise : complete_info_promise_set_) {
promise->Resolve(*result);
}
complete_info_promise_set_.clear();
}

void GPUInfoManager::OnGpuInfoUpdate() {
// Ignore if called when not asked for complete GPUInfo
if (NeedsCompleteGpuInfoCollection())
return;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&GPUInfoManager::ProcessCompleteInfo,
base::Unretained(this)));
}

// Should be posted to the task runner
void GPUInfoManager::CompleteInfoFetcher(scoped_refptr<util::Promise> promise) {
complete_info_promise_set_.push_back(promise);

if (NeedsCompleteGpuInfoCollection()) {
gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
} else {
GPUInfoManager::OnGpuInfoUpdate();
}
}

void GPUInfoManager::FetchCompleteInfo(scoped_refptr<util::Promise> promise) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&GPUInfoManager::CompleteInfoFetcher,
base::Unretained(this), promise));
}

// This fetches the info synchronously, so no need to post to the task queue.
// There cannot be multiple promises as they are resolved synchronously.
void GPUInfoManager::FetchBasicInfo(scoped_refptr<util::Promise> promise) {
gpu::GPUInfo gpu_info;
CollectBasicGraphicsInfo(&gpu_info);
promise->Resolve(*EnumerateGPUInfo(gpu_info));
}

std::unique_ptr<base::DictionaryValue> GPUInfoManager::EnumerateGPUInfo(
gpu::GPUInfo gpu_info) const {
GPUInfoEnumerator enumerator;
gpu_info.EnumerateFields(&enumerator);
return enumerator.GetDictionary();
}

} // namespace atom
49 changes: 49 additions & 0 deletions atom/browser/api/gpuinfo_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#ifndef ATOM_BROWSER_API_GPUINFO_MANAGER_H_
#define ATOM_BROWSER_API_GPUINFO_MANAGER_H_

#include <memory>
#include <unordered_set>
#include <vector>

#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/promise_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/gpu_data_manager_observer.h"

namespace atom {

// GPUInfoManager is a singleton used to manage and fetch GPUInfo
class GPUInfoManager : public content::GpuDataManagerObserver {
public:
static GPUInfoManager* GetInstance();

GPUInfoManager();
~GPUInfoManager() override;
bool NeedsCompleteGpuInfoCollection();
void FetchCompleteInfo(scoped_refptr<util::Promise> promise);
void FetchBasicInfo(scoped_refptr<util::Promise> promise);
void OnGpuInfoUpdate() override;

private:
std::unique_ptr<base::DictionaryValue> EnumerateGPUInfo(
gpu::GPUInfo gpu_info) const;

// These should be posted to the task queue
void CompleteInfoFetcher(scoped_refptr<util::Promise> promise);
void ProcessCompleteInfo();

// This set maintains all the promises that should be fulfilled
// once we have the complete information data
std::vector<scoped_refptr<util::Promise>> complete_info_promise_set_;
content::GpuDataManager* gpu_data_manager_;

DISALLOW_COPY_AND_ASSIGN(GPUInfoManager);
};

} // namespace atom
#endif // ATOM_BROWSER_API_GPUINFO_MANAGER_H_
2 changes: 1 addition & 1 deletion atom/common/promise_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ v8::Maybe<bool> Promise::RejectWithErrorMessage(const std::string& string) {
mate::ConvertToV8(isolate(), error));
}

v8::Local<v8::Object> Promise::GetHandle() const {
v8::Local<v8::Promise> Promise::GetHandle() const {
return GetInner()->GetPromise();
}

Expand Down
Loading
0