From 3ef6bd79e156404ecc7be3fca91711650f081a59 Mon Sep 17 00:00:00 2001 From: jrhodnik Date: Mon, 3 Jun 2019 21:12:13 -0400 Subject: [PATCH] Started implementing BrowserOverlay. --- VRDash/App.config | 6 +- VRDash/MainWindow.xaml | 1 + VRDash/MainWindow.xaml.cs | 14 ++ VRDash/Overlay/BrowserOverlay.xaml | 13 ++ VRDash/Overlay/BrowserOverlay.xaml.cs | 241 ++++++++++++++++++++++++ VRDash/Overlay/WindowOverlay.cs | 2 +- VRDash/Properties/Resources.Designer.cs | 46 ++--- VRDash/Properties/Settings.Designer.cs | 22 +-- VRDash/VRDash.csproj | 29 ++- VRDash/packages.config | 4 + 10 files changed, 333 insertions(+), 45 deletions(-) create mode 100644 VRDash/Overlay/BrowserOverlay.xaml create mode 100644 VRDash/Overlay/BrowserOverlay.xaml.cs diff --git a/VRDash/App.config b/VRDash/App.config index 8e15646..8227adb 100644 --- a/VRDash/App.config +++ b/VRDash/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/VRDash/MainWindow.xaml b/VRDash/MainWindow.xaml index d3da8d0..52812eb 100644 --- a/VRDash/MainWindow.xaml +++ b/VRDash/MainWindow.xaml @@ -5,6 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:VRDash" mc:Ignorable="d" + KeyDown="Window_KeyDown" Title="VRDash" Height="700" Width="800"> diff --git a/VRDash/MainWindow.xaml.cs b/VRDash/MainWindow.xaml.cs index aaaf9ee..5861897 100644 --- a/VRDash/MainWindow.xaml.cs +++ b/VRDash/MainWindow.xaml.cs @@ -217,6 +217,20 @@ namespace VRDash var profile = ProfileManager.LoadProfile(); LoadProfile(profile); } + + private void Window_KeyDown(object sender, KeyEventArgs e) + { + if(e.Key == Key.F1) + { + var conf = new MonitorOverlayConfig(); + conf.Name = "Test Browser"; + conf.Key = "asdfasdf"; + conf.Location = new Overlay.Config.OverlayLocation.DashboardLocation(); + var overlay = new Overlay.BrowserOverlay(conf); + overlay.Create(); + overlay.Show(); + } + } } public class EditorMap diff --git a/VRDash/Overlay/BrowserOverlay.xaml b/VRDash/Overlay/BrowserOverlay.xaml new file mode 100644 index 0000000..7dd3456 --- /dev/null +++ b/VRDash/Overlay/BrowserOverlay.xaml @@ -0,0 +1,13 @@ + + + + + diff --git a/VRDash/Overlay/BrowserOverlay.xaml.cs b/VRDash/Overlay/BrowserOverlay.xaml.cs new file mode 100644 index 0000000..f1dc6ec --- /dev/null +++ b/VRDash/Overlay/BrowserOverlay.xaml.cs @@ -0,0 +1,241 @@ +using CefSharp; +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Valve.VR; +using VRDash.Overlay.Config; + +namespace VRDash.Overlay +{ + /// + /// Interaction logic for BrowserOverlay.xaml + /// + public partial class BrowserOverlay : Window, IOverlay + { + ulong m_OverlayHandle = OpenVR.k_ulOverlayHandleInvalid; + public ulong OverlayHandle { get { return m_OverlayHandle; } } + + ulong m_ThumbnailHandle = OpenVR.k_ulOverlayHandleInvalid; + + public IOverlayConfig OverlayConfig { get { return Config; } } + + //CHANGEME to the BrowserOverlayCOnfig you make later + public IOverlayConfig Config { get; } + + public int CurrentFPS { get; private set; } = 0; + + public bool IsDisposed { get; private set; } = false; + + public event EventHandler OverlayShown; + public event EventHandler OverlayHidden; + public event EventHandler Update; + + bool m_Created = false; + + //CHANGEME to the BrowserOverlayCOnfig you make later + public BrowserOverlay(IOverlayConfig config) + { + Config = config; + InitializeComponent(); + } + + Factory1 m_Factory = null; + Adapter1 m_Adapter = null; + SharpDX.Direct3D11.Device m_Device = null; + + int m_LastWidth = 0; + int m_LastHeight = 0; + + Texture2D m_ScreenTexture = null; + DataStream m_Stream = null; + + + int frames = 0; + DateTime lastFps = DateTime.MinValue; + DateTime lastNameCheck = DateTime.MinValue; + + public void Create() + { + if (m_Created) { throw new Exception("This overlay has already been created."); } + + Config.OverlayLocation.OverlayHandles overlayHandles = Config.Location.CreateOverlay(Config.Key, Config.Name, this); + + m_OverlayHandle = overlayHandles.OverlayHandle; + m_ThumbnailHandle = overlayHandles.ThumbnailHandle; + OpenVR.Overlay.ShowOverlay(m_OverlayHandle); + m_Created = true; + + #region Rendering setup + m_Factory = new Factory1(); + //Get first adapter + m_Adapter = m_Factory.GetAdapter1(0); + //Get device from adapter + m_Device = new SharpDX.Direct3D11.Device(m_Adapter); + #endregion + } + + public void Destroy() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + if (IsDisposed) { return; } + Destroy(); + IsDisposed = true; + } + + public string GetOverlayName() + { + EVROverlayError err = EVROverlayError.None; + StringBuilder sb = new StringBuilder(255); + uint res = OpenVR.Overlay.GetOverlayName(m_OverlayHandle, sb, 255, ref err); + return sb.ToString(); + } + + public void SetOverlayName(string newName) + { + OpenVR.Overlay.SetOverlayName(m_OverlayHandle, newName); + } + + public float GetOverlayWidth() + { + float width = 0f; + OpenVR.Overlay.GetOverlayWidthInMeters(m_OverlayHandle, ref width); + return width; + } + + public void SetOverlayWidth(float width) + { + OpenVR.Overlay.SetOverlayWidthInMeters(m_OverlayHandle, width); + } + + private void cwbBrowser_IsBrowserInitializedChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if ((bool)e.NewValue) + { + cwbBrowser.LoadHtml(""); + } + } + + #region Rendering shit + + private void cwbBrowser_Paint(object sender, CefSharp.Wpf.PaintEventArgs e) + { + if (!m_Created) { return; } + Update?.Invoke(this, null); + + if (m_ScreenTexture == null || (m_LastWidth != e.Width || m_LastHeight != e.Height)) + { + m_LastWidth = e.Width; + m_LastHeight = e.Height; + + if (m_ScreenTexture != null) + { + m_ScreenTexture.Dispose(); + + //Dispose not freeing screenTexture: https://gamedev.stackexchange.com/questions/93311/freeing-texture-memory-in-sharpdx-what-am-i-missing + m_Device.ImmediateContext.ClearState(); + m_Device.ImmediateContext.Flush(); + } + + var textureDesc = new Texture2DDescription + { + CpuAccessFlags = CpuAccessFlags.Write, + BindFlags = BindFlags.ShaderResource, + Format = Format.B8G8R8A8_UNorm, + //Format = Format.B8G8R8A8_UNorm_SRgb, + Width = e.Width, + Height = e.Height, + OptionFlags = ResourceOptionFlags.None, + MipLevels = 1, + ArraySize = 1, + SampleDescription = { Count = 1, Quality = 0 }, + Usage = ResourceUsage.Dynamic + }; + m_ScreenTexture = new Texture2D(m_Device, textureDesc); + m_Stream = new DataStream(4 * e.Width * e.Height, true, true); + + OpenVR.Overlay.SetOverlayWidthInMeters(m_OverlayHandle, Config.OverlayWidth); + + HmdVector2_t vecWindowSize = new HmdVector2_t() { v0 = e.Width, v1 = e.Height }; + OpenVR.Overlay.SetOverlayMouseScale(m_OverlayHandle, ref vecWindowSize); + this.GetLogger().Info($"Browser resized, texture updated. ({e.Width}x{e.Height})"); + } + + DataBox databox = m_Device.ImmediateContext.MapSubresource(m_ScreenTexture, 0, MapMode.WriteDiscard, + SharpDX.Direct3D11.MapFlags.None, out m_Stream); + + + int stride = e.Width * 4; + + if (!databox.IsEmpty) + { + int count = 4 * e.Width * e.Height; + + //Stride compensation. Sometimes the BMP and DX texture strides are different. This fixes it. + if (databox.RowPitch == stride) + { + m_Stream.Write(e.Buffer, 0, count); + } + //Truncate the extra BMP bytes. + else if (databox.RowPitch < stride) + { + for (int i = 0; i < e.Height; i++) + { + m_Stream.Write(e.Buffer, (stride * i), databox.RowPitch); + } + } + //Add some junk on empty bytes on the end to make everyone happy. + else if (databox.RowPitch > stride) + { + int difference = databox.RowPitch - stride; + byte[] junk = new byte[difference]; + for (int i = 0; i < e.Height; i++) + { + m_Stream.Write(e.Buffer, (stride * i), stride); + m_Stream.Write(junk, 0, difference); + } + } + //stream.Write(data.Scan0, 0, count); + } + + m_Device.ImmediateContext.UpdateSubresource(ref databox, m_ScreenTexture, 0, stride, 1); + + var texture = new Texture_t(); + texture.handle = m_ScreenTexture.NativePointer; + texture.eType = ETextureType.DirectX; + texture.eColorSpace = EColorSpace.Auto; + EVROverlayError result = OpenVR.Overlay.SetOverlayTexture(m_OverlayHandle, ref texture); + if (result != EVROverlayError.None) + { + + this.GetLogger().Warn($"Error rendering: {result}"); + } + + m_Device.ImmediateContext.UnmapSubresource(m_ScreenTexture, 0); + + + + //FIXME Later... + //frames++; + + } + + #endregion + } +} diff --git a/VRDash/Overlay/WindowOverlay.cs b/VRDash/Overlay/WindowOverlay.cs index 03a40f5..64a41c5 100644 --- a/VRDash/Overlay/WindowOverlay.cs +++ b/VRDash/Overlay/WindowOverlay.cs @@ -44,7 +44,7 @@ namespace VRDash.Overlay public ulong ThumbnailIcon { get { return m_ThumbnailIcon; } } public IOverlayConfig OverlayConfig { get { return Config; } } - public WindowOverlayConfig Config { get; } + public WindowOverlayConfig Config { get; private set; } //internal string m_Key; diff --git a/VRDash/Properties/Resources.Designer.cs b/VRDash/Properties/Resources.Designer.cs index feb7a42..f8d57bb 100644 --- a/VRDash/Properties/Resources.Designer.cs +++ b/VRDash/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace VRDash.Properties -{ - - +namespace VRDash.Properties { + using System; + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,51 +19,43 @@ namespace VRDash.Properties // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - + internal class Resources { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { + internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VDash.Properties.Resources", typeof(Resources).Assembly); + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VRDash.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { + internal static global::System.Globalization.CultureInfo Culture { + get { return resourceCulture; } - set - { + set { resourceCulture = value; } } diff --git a/VRDash/Properties/Settings.Designer.cs b/VRDash/Properties/Settings.Designer.cs index 854fbfe..7a1563d 100644 --- a/VRDash/Properties/Settings.Designer.cs +++ b/VRDash/Properties/Settings.Designer.cs @@ -8,21 +8,17 @@ // //------------------------------------------------------------------------------ -namespace VRDash.Properties -{ - - +namespace VRDash.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { + + public static Settings Default { + get { return defaultInstance; } } diff --git a/VRDash/VRDash.csproj b/VRDash/VRDash.csproj index 8c09fc4..7eceaea 100644 --- a/VRDash/VRDash.csproj +++ b/VRDash/VRDash.csproj @@ -1,5 +1,9 @@  + + + + Debug @@ -8,11 +12,14 @@ WinExe VRDash VRDash - v4.5 + v4.5.2 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 true + + + AnyCPU @@ -95,6 +102,9 @@ Designer + + BrowserOverlay.xaml + @@ -165,6 +175,10 @@ MainWindow.xaml Code + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -243,4 +257,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/VRDash/packages.config b/VRDash/packages.config index 5e2960d..ef9c35d 100644 --- a/VRDash/packages.config +++ b/VRDash/packages.config @@ -1,5 +1,9 @@  + + + +