1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/gpu/gpu_internals_ui.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/i18n/time_formatting.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/sys_info.h"
16 #include "base/values.h"
17 #include "cc/base/switches.h"
18 #include "content/browser/gpu/gpu_data_manager_impl.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/compositor_util.h"
21 #include "content/public/browser/gpu_data_manager_observer.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_ui.h"
24 #include "content/public/browser/web_ui_data_source.h"
25 #include "content/public/browser/web_ui_message_handler.h"
26 #include "content/public/common/content_client.h"
27 #include "content/public/common/content_switches.h"
28 #include "content/public/common/url_constants.h"
29 #include "gpu/config/gpu_feature_type.h"
30 #include "gpu/config/gpu_info.h"
31 #include "grit/content_resources.h"
34 #if defined(ANGLE_DX11)
35 #include "third_party/angle_dx11/src/common/version.h"
37 #include "third_party/angle/src/common/version.h"
43 struct GpuFeatureInfo
{
47 std::string disabled_description
;
48 bool fallback_to_software
;
51 WebUIDataSource
* CreateGpuHTMLSource() {
52 WebUIDataSource
* source
= WebUIDataSource::Create(kChromeUIGpuHost
);
54 source
->SetJsonPath("strings.js");
55 source
->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS
);
56 source
->SetDefaultResource(IDR_GPU_INTERNALS_HTML
);
60 base::DictionaryValue
* NewDescriptionValuePair(const std::string
& desc
,
61 const std::string
& value
) {
62 base::DictionaryValue
* dict
= new base::DictionaryValue();
63 dict
->SetString("description", desc
);
64 dict
->SetString("value", value
);
68 base::DictionaryValue
* NewDescriptionValuePair(const std::string
& desc
,
70 base::DictionaryValue
* dict
= new base::DictionaryValue();
71 dict
->SetString("description", desc
);
72 dict
->Set("value", value
);
76 base::Value
* NewStatusValue(const char* name
, const char* status
) {
77 base::DictionaryValue
* value
= new base::DictionaryValue();
78 value
->SetString("name", name
);
79 value
->SetString("status", status
);
84 // Output DxDiagNode tree as nested array of {description,value} pairs
85 base::ListValue
* DxDiagNodeToList(const gpu::DxDiagNode
& node
) {
86 base::ListValue
* list
= new base::ListValue();
87 for (std::map
<std::string
, std::string
>::const_iterator it
=
89 it
!= node
.values
.end();
91 list
->Append(NewDescriptionValuePair(it
->first
, it
->second
));
94 for (std::map
<std::string
, gpu::DxDiagNode
>::const_iterator it
=
95 node
.children
.begin();
96 it
!= node
.children
.end();
98 base::ListValue
* sublist
= DxDiagNodeToList(it
->second
);
99 list
->Append(NewDescriptionValuePair(it
->first
, sublist
));
105 std::string
GPUDeviceToString(const gpu::GPUInfo::GPUDevice
& gpu
) {
106 std::string vendor
= base::StringPrintf("0x%04x", gpu
.vendor_id
);
107 if (!gpu
.vendor_string
.empty())
108 vendor
+= " [" + gpu
.vendor_string
+ "]";
109 std::string device
= base::StringPrintf("0x%04x", gpu
.device_id
);
110 if (!gpu
.device_string
.empty())
111 device
+= " [" + gpu
.device_string
+ "]";
112 return base::StringPrintf(
113 "VENDOR = %s, DEVICE= %s", vendor
.c_str(), device
.c_str());
116 base::DictionaryValue
* GpuInfoAsDictionaryValue() {
117 gpu::GPUInfo gpu_info
= GpuDataManagerImpl::GetInstance()->GetGPUInfo();
118 base::ListValue
* basic_info
= new base::ListValue();
119 basic_info
->Append(NewDescriptionValuePair(
120 "Initialization time",
121 base::Int64ToString(gpu_info
.initialization_time
.InMilliseconds())));
122 basic_info
->Append(NewDescriptionValuePair(
123 "Sandboxed", new base::FundamentalValue(gpu_info
.sandboxed
)));
124 basic_info
->Append(NewDescriptionValuePair(
125 "GPU0", GPUDeviceToString(gpu_info
.gpu
)));
126 for (size_t i
= 0; i
< gpu_info
.secondary_gpus
.size(); ++i
) {
127 basic_info
->Append(NewDescriptionValuePair(
128 base::StringPrintf("GPU%d", static_cast<int>(i
+ 1)),
129 GPUDeviceToString(gpu_info
.secondary_gpus
[i
])));
131 basic_info
->Append(NewDescriptionValuePair(
132 "Optimus", new base::FundamentalValue(gpu_info
.optimus
)));
133 basic_info
->Append(NewDescriptionValuePair(
134 "AMD switchable", new base::FundamentalValue(gpu_info
.amd_switchable
)));
135 if (gpu_info
.lenovo_dcute
) {
136 basic_info
->Append(NewDescriptionValuePair(
137 "Lenovo dCute", new base::FundamentalValue(true)));
139 if (gpu_info
.display_link_version
.IsValid()) {
140 basic_info
->Append(NewDescriptionValuePair(
141 "DisplayLink Version", gpu_info
.display_link_version
.GetString()));
143 basic_info
->Append(NewDescriptionValuePair("Driver vendor",
144 gpu_info
.driver_vendor
));
145 basic_info
->Append(NewDescriptionValuePair("Driver version",
146 gpu_info
.driver_version
));
147 basic_info
->Append(NewDescriptionValuePair("Driver date",
148 gpu_info
.driver_date
));
149 basic_info
->Append(NewDescriptionValuePair("Pixel shader version",
150 gpu_info
.pixel_shader_version
));
151 basic_info
->Append(NewDescriptionValuePair("Vertex shader version",
152 gpu_info
.vertex_shader_version
));
153 basic_info
->Append(NewDescriptionValuePair("Machine model",
154 gpu_info
.machine_model
));
155 basic_info
->Append(NewDescriptionValuePair("GL version",
156 gpu_info
.gl_version
));
157 basic_info
->Append(NewDescriptionValuePair("GL_VENDOR",
158 gpu_info
.gl_vendor
));
159 basic_info
->Append(NewDescriptionValuePair("GL_RENDERER",
160 gpu_info
.gl_renderer
));
161 basic_info
->Append(NewDescriptionValuePair("GL_VERSION",
162 gpu_info
.gl_version_string
));
163 basic_info
->Append(NewDescriptionValuePair("GL_EXTENSIONS",
164 gpu_info
.gl_extensions
));
165 basic_info
->Append(NewDescriptionValuePair("Window system binding vendor",
166 gpu_info
.gl_ws_vendor
));
167 basic_info
->Append(NewDescriptionValuePair("Window system binding version",
168 gpu_info
.gl_ws_version
));
169 basic_info
->Append(NewDescriptionValuePair("Window system binding extensions",
170 gpu_info
.gl_ws_extensions
));
172 base::DictionaryValue
* info
= new base::DictionaryValue();
173 info
->Set("basic_info", basic_info
);
176 base::ListValue
* perf_info
= new base::ListValue();
177 perf_info
->Append(NewDescriptionValuePair(
179 base::StringPrintf("%.1f", gpu_info
.performance_stats
.graphics
)));
180 perf_info
->Append(NewDescriptionValuePair(
182 base::StringPrintf("%.1f", gpu_info
.performance_stats
.gaming
)));
183 perf_info
->Append(NewDescriptionValuePair(
185 base::StringPrintf("%.1f", gpu_info
.performance_stats
.overall
)));
186 info
->Set("performance_info", perf_info
);
188 base::Value
* dx_info
= gpu_info
.dx_diagnostics
.children
.size() ?
189 DxDiagNodeToList(gpu_info
.dx_diagnostics
) :
190 base::Value::CreateNullValue();
191 info
->Set("diagnostics", dx_info
);
197 // Determine if accelerated-2d-canvas is supported, which depends on whether
198 // lose_context could happen.
199 bool SupportsAccelerated2dCanvas() {
200 if (GpuDataManagerImpl::GetInstance()->GetGPUInfo().can_lose_context
)
205 base::Value
* GetFeatureStatus() {
206 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
207 GpuDataManagerImpl
* manager
= GpuDataManagerImpl::GetInstance();
208 std::string gpu_access_blocked_reason
;
209 bool gpu_access_blocked
=
210 !manager
->GpuAccessAllowed(&gpu_access_blocked_reason
);
212 base::DictionaryValue
* status
= new base::DictionaryValue();
214 const GpuFeatureInfo kGpuFeatureInfo
[] = {
217 manager
->IsFeatureBlacklisted(
218 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
),
219 command_line
.HasSwitch(switches::kDisableAccelerated2dCanvas
) ||
220 !SupportsAccelerated2dCanvas(),
221 "Accelerated 2D canvas is unavailable: either disabled at the command"
222 " line or not supported by the current system.",
227 manager
->IsFeatureBlacklisted(
228 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
),
229 command_line
.HasSwitch(switches::kDisableAcceleratedCompositing
),
230 "Accelerated compositing has been disabled, either via about:flags or"
231 " command line. This adversely affects performance of all hardware"
232 " accelerated features.",
237 manager
->IsFeatureBlacklisted(
238 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
) ||
239 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS
),
240 command_line
.HasSwitch(switches::kDisableAcceleratedLayers
),
241 "Accelerated layers have been disabled at the command line.",
246 manager
->IsFeatureBlacklisted(
247 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
) ||
248 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS
),
249 command_line
.HasSwitch(cc::switches::kDisableThreadedAnimation
) ||
250 command_line
.HasSwitch(switches::kDisableAcceleratedCompositing
) ||
251 command_line
.HasSwitch(switches::kDisableAcceleratedLayers
),
252 "Accelerated CSS animation has been disabled at the command line.",
257 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
),
258 #if defined(OS_ANDROID)
259 !command_line
.HasSwitch(switches::kEnableExperimentalWebGL
),
261 command_line
.HasSwitch(switches::kDisableExperimentalWebGL
),
263 "WebGL has been disabled, either via about:flags or command line.",
268 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING
),
269 command_line
.HasSwitch(switches::kDisableGLMultisampling
),
270 "Multisampling has been disabled, either via about:flags or command"
276 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D
),
277 command_line
.HasSwitch(switches::kDisableFlash3d
),
278 "Using 3d in flash has been disabled, either via about:flags or"
284 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D
),
285 command_line
.HasSwitch(switches::kDisableFlashStage3d
),
286 "Using Stage3d in Flash has been disabled, either via about:flags or"
291 "flash_stage3d_baseline",
292 manager
->IsFeatureBlacklisted(
293 gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE
) ||
294 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D
),
295 command_line
.HasSwitch(switches::kDisableFlashStage3d
),
296 "Using Stage3d Baseline profile in Flash has been disabled, either"
297 " via about:flags or command line.",
302 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING
),
303 command_line
.HasSwitch(switches::kDisableImageTransportSurface
),
304 "Sharing textures between processes has been disabled, either via"
305 " about:flags or command line.",
310 manager
->IsFeatureBlacklisted(
311 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE
),
312 command_line
.HasSwitch(switches::kDisableAcceleratedVideoDecode
),
313 "Accelerated video decode has been disabled, either via about:flags"
319 manager
->IsFeatureBlacklisted(
320 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO
),
321 command_line
.HasSwitch(switches::kDisableAcceleratedVideo
) ||
322 command_line
.HasSwitch(switches::kDisableAcceleratedCompositing
),
323 "Accelerated video presentation has been disabled, either via"
324 " about:flags or command line.",
327 #if defined(OS_CHROMEOS)
330 manager
->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING
),
331 command_line
.HasSwitch(switches::kDisablePanelFitting
),
332 "Panel fitting has been disabled, either via about:flags or command"
338 "force_compositing_mode",
339 manager
->IsFeatureBlacklisted(
340 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE
) &&
341 !IsForceCompositingModeEnabled(),
342 !IsForceCompositingModeEnabled() &&
343 !manager
->IsFeatureBlacklisted(
344 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE
),
345 "Force compositing mode is off, either disabled at the command"
346 " line or not supported by the current system.",
350 const size_t kNumFeatures
= sizeof(kGpuFeatureInfo
) / sizeof(GpuFeatureInfo
);
352 // Build the feature_status field.
354 base::ListValue
* feature_status_list
= new base::ListValue();
356 for (size_t i
= 0; i
< kNumFeatures
; ++i
) {
357 // force_compositing_mode status is part of the compositing status.
358 if (kGpuFeatureInfo
[i
].name
== "force_compositing_mode")
362 if (kGpuFeatureInfo
[i
].disabled
) {
364 if (kGpuFeatureInfo
[i
].name
== "css_animation") {
365 status
+= "_software_animated";
366 } else if (kGpuFeatureInfo
[i
].name
== "raster") {
367 if (cc::switches::IsImplSidePaintingEnabled())
368 status
+= "_software_multithreaded";
370 status
+= "_software";
372 if (kGpuFeatureInfo
[i
].fallback_to_software
)
373 status
+= "_software";
377 } else if (GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) {
378 status
= "unavailable_software";
379 } else if (kGpuFeatureInfo
[i
].blocked
||
380 gpu_access_blocked
) {
381 status
= "unavailable";
382 if (kGpuFeatureInfo
[i
].fallback_to_software
)
383 status
+= "_software";
388 if (kGpuFeatureInfo
[i
].name
== "webgl" &&
389 (command_line
.HasSwitch(switches::kDisableAcceleratedCompositing
) ||
390 manager
->IsFeatureBlacklisted(
391 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
)))
392 status
+= "_readback";
393 bool has_thread
= IsThreadedCompositingEnabled();
394 if (kGpuFeatureInfo
[i
].name
== "compositing") {
395 bool force_compositing
= IsForceCompositingModeEnabled();
396 if (force_compositing
)
399 status
+= "_threaded";
401 if (kGpuFeatureInfo
[i
].name
== "css_animation") {
403 status
= "accelerated_threaded";
405 status
= "accelerated";
408 // TODO(reveman): Remove this when crbug.com/223286 has been fixed.
409 if (kGpuFeatureInfo
[i
].name
== "raster" &&
410 cc::switches::IsImplSidePaintingEnabled()) {
411 status
= "disabled_software_multithreaded";
413 feature_status_list
->Append(
414 NewStatusValue(kGpuFeatureInfo
[i
].name
.c_str(), status
.c_str()));
416 gpu::GpuSwitchingOption gpu_switching_option
=
417 GpuDataManagerImpl::GetInstance()->GetGpuSwitchingOption();
418 if (gpu_switching_option
!= gpu::GPU_SWITCHING_OPTION_UNKNOWN
) {
419 std::string gpu_switching
;
420 switch (gpu_switching_option
) {
421 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC
:
422 gpu_switching
= "gpu_switching_automatic";
424 case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE
:
425 gpu_switching
= "gpu_switching_force_discrete";
427 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED
:
428 gpu_switching
= "gpu_switching_force_integrated";
433 feature_status_list
->Append(
434 NewStatusValue("gpu_switching", gpu_switching
.c_str()));
436 status
->Set("featureStatus", feature_status_list
);
439 // Build the problems list.
441 base::ListValue
* problem_list
= new base::ListValue();
442 GpuDataManagerImpl::GetInstance()->GetBlacklistReasons(problem_list
);
444 if (gpu_access_blocked
) {
445 base::DictionaryValue
* problem
= new base::DictionaryValue();
446 problem
->SetString("description",
447 "GPU process was unable to boot: " + gpu_access_blocked_reason
);
448 problem
->Set("crBugs", new base::ListValue());
449 problem
->Set("webkitBugs", new base::ListValue());
450 problem_list
->Insert(0, problem
);
453 for (size_t i
= 0; i
< kNumFeatures
; ++i
) {
454 if (kGpuFeatureInfo
[i
].disabled
) {
455 base::DictionaryValue
* problem
= new base::DictionaryValue();
457 "description", kGpuFeatureInfo
[i
].disabled_description
);
458 problem
->Set("crBugs", new base::ListValue());
459 problem
->Set("webkitBugs", new base::ListValue());
460 problem_list
->Append(problem
);
464 status
->Set("problems", problem_list
);
467 // Build driver bug workaround list.
469 base::ListValue
* workaround_list
= new base::ListValue();
470 GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds(workaround_list
);
471 status
->Set("workarounds", workaround_list
);
477 // This class receives javascript messages from the renderer.
478 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
479 // this class's methods are expected to run on the UI thread.
480 class GpuMessageHandler
481 : public WebUIMessageHandler
,
482 public base::SupportsWeakPtr
<GpuMessageHandler
>,
483 public GpuDataManagerObserver
{
486 virtual ~GpuMessageHandler();
488 // WebUIMessageHandler implementation.
489 virtual void RegisterMessages() OVERRIDE
;
491 // GpuDataManagerObserver implementation.
492 virtual void OnGpuInfoUpdate() OVERRIDE
;
493 virtual void OnGpuSwitching() OVERRIDE
;
496 void OnBrowserBridgeInitialized(const base::ListValue
* list
);
497 void OnCallAsync(const base::ListValue
* list
);
499 // Submessages dispatched from OnCallAsync
500 base::Value
* OnRequestClientInfo(const base::ListValue
* list
);
501 base::Value
* OnRequestLogMessages(const base::ListValue
* list
);
504 // True if observing the GpuDataManager (re-attaching as observer would
508 DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler
);
511 ////////////////////////////////////////////////////////////////////////////////
515 ////////////////////////////////////////////////////////////////////////////////
517 GpuMessageHandler::GpuMessageHandler()
518 : observing_(false) {
521 GpuMessageHandler::~GpuMessageHandler() {
522 GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
525 /* BrowserBridge.callAsync prepends a requestID to these messages. */
526 void GpuMessageHandler::RegisterMessages() {
527 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
529 web_ui()->RegisterMessageCallback("browserBridgeInitialized",
530 base::Bind(&GpuMessageHandler::OnBrowserBridgeInitialized
,
531 base::Unretained(this)));
532 web_ui()->RegisterMessageCallback("callAsync",
533 base::Bind(&GpuMessageHandler::OnCallAsync
,
534 base::Unretained(this)));
537 void GpuMessageHandler::OnCallAsync(const base::ListValue
* args
) {
538 DCHECK_GE(args
->GetSize(), static_cast<size_t>(2));
539 // unpack args into requestId, submessage and submessageArgs
541 const base::Value
* requestId
;
542 ok
= args
->Get(0, &requestId
);
545 std::string submessage
;
546 ok
= args
->GetString(1, &submessage
);
549 base::ListValue
* submessageArgs
= new base::ListValue();
550 for (size_t i
= 2; i
< args
->GetSize(); ++i
) {
551 const base::Value
* arg
;
552 ok
= args
->Get(i
, &arg
);
555 base::Value
* argCopy
= arg
->DeepCopy();
556 submessageArgs
->Append(argCopy
);
559 // call the submessage handler
560 base::Value
* ret
= NULL
;
561 if (submessage
== "requestClientInfo") {
562 ret
= OnRequestClientInfo(submessageArgs
);
563 } else if (submessage
== "requestLogMessages") {
564 ret
= OnRequestLogMessages(submessageArgs
);
565 } else { // unrecognized submessage
567 delete submessageArgs
;
570 delete submessageArgs
;
572 // call BrowserBridge.onCallAsyncReply with result
574 web_ui()->CallJavascriptFunction("browserBridge.onCallAsyncReply",
579 web_ui()->CallJavascriptFunction("browserBridge.onCallAsyncReply",
584 void GpuMessageHandler::OnBrowserBridgeInitialized(
585 const base::ListValue
* args
) {
586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
588 // Watch for changes in GPUInfo
590 GpuDataManagerImpl::GetInstance()->AddObserver(this);
593 // Tell GpuDataManager it should have full GpuInfo. If the
594 // Gpu process has not run yet, this will trigger its launch.
595 GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded();
597 // Run callback immediately in case the info is ready and no update in the
602 base::Value
* GpuMessageHandler::OnRequestClientInfo(
603 const base::ListValue
* list
) {
604 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
606 base::DictionaryValue
* dict
= new base::DictionaryValue();
608 dict
->SetString("version", GetContentClient()->GetProduct());
609 dict
->SetString("command_line",
610 CommandLine::ForCurrentProcess()->GetCommandLineString());
611 dict
->SetString("operating_system",
612 base::SysInfo::OperatingSystemName() + " " +
613 base::SysInfo::OperatingSystemVersion());
614 dict
->SetString("angle_revision", base::UintToString(BUILD_REVISION
));
615 dict
->SetString("graphics_backend", "Skia");
616 dict
->SetString("blacklist_version",
617 GpuDataManagerImpl::GetInstance()->GetBlacklistVersion());
618 dict
->SetString("driver_bug_list_version",
619 GpuDataManagerImpl::GetInstance()->GetDriverBugListVersion());
624 base::Value
* GpuMessageHandler::OnRequestLogMessages(const base::ListValue
*) {
625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
627 return GpuDataManagerImpl::GetInstance()->GetLogMessages();
630 void GpuMessageHandler::OnGpuInfoUpdate() {
632 scoped_ptr
<base::DictionaryValue
> gpu_info_val(GpuInfoAsDictionaryValue());
634 // Add in blacklisting features
635 base::Value
* feature_status
= GetFeatureStatus();
637 gpu_info_val
->Set("featureStatus", feature_status
);
639 // Send GPU Info to javascript.
640 web_ui()->CallJavascriptFunction("browserBridge.onGpuInfoUpdate",
641 *(gpu_info_val
.get()));
644 void GpuMessageHandler::OnGpuSwitching() {
645 GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded();
651 ////////////////////////////////////////////////////////////////////////////////
655 ////////////////////////////////////////////////////////////////////////////////
657 GpuInternalsUI::GpuInternalsUI(WebUI
* web_ui
)
658 : WebUIController(web_ui
) {
659 web_ui
->AddMessageHandler(new GpuMessageHandler());
661 // Set up the chrome://gpu/ source.
662 BrowserContext
* browser_context
=
663 web_ui
->GetWebContents()->GetBrowserContext();
664 WebUIDataSource::Add(browser_context
, CreateGpuHTMLSource());
667 } // namespace content