C#
WebBrowser
GPUレンダリング
qnoteDay 20

WebBrowserコントロールでGPUレンダリングを使用してみた

More than 1 year has passed since last update.

WebBrowserコントロールを使用し動画を再生してみたものの、動画がカクカクしてfpsがでてないなーっと困ったお話です。

HTMLにvideoタグを貼り付ける

HTMLのページに動画を貼り付ける場合、Flashは使用せずHTML5のvideoタグを使用して表示します。

video.html
<video src="sample.mp4"></video>

とってもシンプルですが、WebBrowserコントロールで生成したブラウザでは再生される動画がカクついてしまいます。今回使用したサンプル動画は30fpsのmp4になりますが、明らかに10fpsくらいしか出ていない感じです。試しにChromeで表示してみると滑らかに描画されIEベースだとダメなのかなーと諦めておりました。
しかし!IE11で再生すると滑らか!

カクカクの原因調査

動画のfpsがでないということは、レンダリングがうまくできてないのかなと考え調べてみると
あった!GPUレンダリングの項目が!
WebBrowserコントロールはデフォルトでCPUでレンダリング(ソフトウェア)が使われていることが判明。

マイクロソフトが提供しているGPUのレンダリングテストページを使用して、WebBrowserコントロールでページを表示してみます
GPUレンダリングのテストページ
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/fishietank/

to.jpg

結果は8fps。Chromeで表示すると60fpsになるのでものすごく重いことがわかります。

GPUレンダリングを有効にする

GPUレンダリングを有効にするためには、まずレジストリの変更が必要となります。

レジストリエディタを起動して下記キーの変更を行います
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_GPU_RENDERING
に実行ファイル名の設定を作り、値に1を指定すると有効(0で無効)になります。

詳しくは
https://msdn.microsoft.com/en-us/library/ee330731(v=vs.85).aspx#gpu_rendering
に仕様が載っております。

ついでにIEのバージョンも指定する

使用するIEのバージョンが新しければレンダリングも早くなりそうな気がする!というわけで、使用するIEを指定してあげましょう。
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

先ほどと同じく実行ファイルを設定し値を10進数で入力します。

10進の値 IEのバージョン
11001 edgeモード
11000 IE11モード
10000 IE10モード
10001 IE10 Standardsモード
9000 IE9モード
9999 IE9 Standardsモード

レジストリを書き換えるのは面倒

自分だけで使用する場合は直接レジストリを書き換えるのもありですが、レジストリエディタで書き換えるのは面倒なので、プログラムに変更処理を追加します。

gpu_render.cs
var executablePathForDebug = Application.ExecutablePath.Replace(".EXE", ".vshost.EXE");
var gpu_render = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_GPU_RENDERING");
gpu_render.SetValue(Path.GetFileName(Application.ExecutablePath), 1);
gpu_render.SetValue(Path.GetFileName(executablePathForDebug), 1);
gpu_render.Close();

実行ファイル名はデバッグ時とリリース時で異なりますので、Application.ExecutablePath.Replace(".EXE", ".vshost.EXE");
でデバッグの実行ファイル名を取得し追加します。

ついでにIEのバージョンも変更

ie_emulation.cs
var targetIEVer = 11000;
var executablePathForDebug = Application.ExecutablePath.Replace(".EXE", ".vshost.EXE");
var browserEmulationRegkey = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION");

var currentIEVer = (int)browserEmulationRegkey.GetValue(Path.GetFileName(Application.ExecutablePath));
var currentIEVerForDebug = (int)browserEmulationRegkey.GetValue(Path.GetFileName(executablePathForDebug));
if (targetIEVer == currentIEVer && targetIEVer == currentIEVerForDebug)
{
  return;
}
browserEmulationRegkey.SetValue(Path.GetFileName(Application.ExecutablePath), targetIEVer);
browserEmulationRegkey.SetValue(Path.GetFileName(executablePathForDebug), targetIEVer);
browserEmulationRegkey.Close();

結果

af.jpg

FishIE Tankで再度テスト。先程は8fpsでしたが最大値の60fpsで描画されるようになりました。
カクカクだった動画も滑らかに再生されGPUレンダリングの必要性を感じる結果となりました。
ちなみに使用している環境はグラフィックカードがGTX745、CPUはCore i7-4790で行っております。