diff options
51 files changed, 4691 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore index de8306ff28f..d3721023fe5 100644 --- a/.gitignore +++ b/.gitignore @@ -48,37 +48,39 @@ capture_webrender/ support/hololens/x64/ support/hololens/ARM/ -support/hololens/Generated\ Files +support/hololens/ServoApp/x64/ +support/hololens/ServoApp/ARM/ +support/hololens/ServoApp/Generated\ Files # Ignore thumbnails created by Windows -support/hololens/Thumbs.db +support/hololens/ServoApp/Thumbs.db # Ignore files built by Visual Studio -support/hololens/*.obj -support/hololens/*.exe -support/hololens/*.pdb -support/hololens/*.user -support/hololens/*.aps -support/hololens/*.pch -support/hololens/*.vspscc -support/hololens/*_i.c -support/hololens/*_p.c -support/hololens/*.ncb -support/hololens/*.suo -support/hololens/*.tlb -support/hololens/*.tlh -support/hololens/*.bak -support/hololens/*.cache -support/hololens/*.ilk -support/hololens/*.log -support/hololens/[Bb]in -support/hololens/[Dd]ebug*/ -support/hololens/*.lib -support/hololens/*.sbr -support/hololens/obj/ -support/hololens/[Rr]elease*/ -support/hololens/_ReSharper*/ -support/hololens/[Tt]est[Rr]esult* +support/hololens/ServoApp/*.obj +support/hololens/ServoApp/*.exe +support/hololens/ServoApp/*.pdb +support/hololens/ServoApp/*.user +support/hololens/ServoApp/*.aps +support/hololens/ServoApp/*.pch +support/hololens/ServoApp/*.vspscc +support/hololens/ServoApp/*_i.c +support/hololens/ServoApp/*_p.c +support/hololens/ServoApp/*.ncb +support/hololens/ServoApp/*.suo +support/hololens/ServoApp/*.tlb +support/hololens/ServoApp/*.tlh +support/hololens/ServoApp/*.bak +support/hololens/ServoApp/*.cache +support/hololens/ServoApp/*.ilk +support/hololens/ServoApp/*.log +support/hololens/ServoApp/[Bb]in +support/hololens/ServoApp/[Dd]ebug*/ +support/hololens/ServoApp/*.lib +support/hololens/ServoApp/*.sbr +support/hololens/ServoApp/obj/ +support/hololens/ServoApp/[Rr]elease*/ +support/hololens/ServoApp/_ReSharper*/ +support/hololens/ServoApp/[Tt]est[Rr]esult* support/hololens/.vs/ # Nuget packages folder diff --git a/servo-tidy.toml b/servo-tidy.toml index 9d49ff467a5..e5aaeb9d12e 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -78,6 +78,7 @@ files = [ directories = [ # Upstream "./support/android/apk", + "./support/hololens", "./support/linux/gstreamer", "./support/magicleap/Servo2D/.vscode", "./support/magicleap/Servo2D/code/inc.gen", diff --git a/support/hololens/ServoApp.sln b/support/hololens/ServoApp.sln new file mode 100644 index 00000000000..af25f2d8d80 --- /dev/null +++ b/support/hololens/ServoApp.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.705 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServoApp", "ServoApp\ServoApp.vcxproj", "{0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|ARM.ActiveCfg = Debug|ARM + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|ARM.Build.0 = Debug|ARM + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|ARM.Deploy.0 = Debug|ARM + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|x64.ActiveCfg = Debug|x64 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|x64.Build.0 = Debug|x64 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|x64.Deploy.0 = Debug|x64 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|x86.ActiveCfg = Debug|Win32 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|x86.Build.0 = Debug|Win32 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Debug|x86.Deploy.0 = Debug|Win32 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|ARM.ActiveCfg = Release|ARM + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|ARM.Build.0 = Release|ARM + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|ARM.Deploy.0 = Release|ARM + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|x64.ActiveCfg = Release|x64 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|x64.Build.0 = Release|x64 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|x64.Deploy.0 = Release|x64 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|x86.ActiveCfg = Release|Win32 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|x86.Build.0 = Release|Win32 + {0EAB7D8B-97FD-4C92-8BB2-D5691B3D5ABD}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E7A46429-FCAF-424D-B65F-A6395E915F23} + EndGlobalSection +EndGlobal diff --git a/support/hololens/ServoApp/App.cpp b/support/hololens/ServoApp/App.cpp new file mode 100644 index 00000000000..e373f05210d --- /dev/null +++ b/support/hololens/ServoApp/App.cpp @@ -0,0 +1,72 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "pch.h" +#include "App.h" +#include "BrowserPage.h" + +using namespace winrt::Windows::ApplicationModel; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Windows::UI::Xaml::Navigation; +using namespace winrt::ServoApp; +using namespace winrt::ServoApp::implementation; + +App::App() { + InitializeComponent(); + Suspending({this, &App::OnSuspending}); + +#if defined _DEBUG && \ + !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException( + [this](IInspectable const &, UnhandledExceptionEventArgs const &e) { + if (IsDebuggerPresent()) { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); +#endif +} + +void App::OnLaunched(LaunchActivatedEventArgs const &e) { + Frame rootFrame{nullptr}; + auto content = Window::Current().Content(); + if (content) { + rootFrame = content.try_as<Frame>(); + } + + if (rootFrame == nullptr) { + rootFrame = Frame(); + + rootFrame.NavigationFailed({this, &App::OnNavigationFailed}); + + if (e.PrelaunchActivated() == false) { + if (rootFrame.Content() == nullptr) { + rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>(), + box_value(e.Arguments())); + } + Window::Current().Content(rootFrame); + Window::Current().Activate(); + } + } else { + if (e.PrelaunchActivated() == false) { + if (rootFrame.Content() == nullptr) { + rootFrame.Navigate(xaml_typename<ServoApp::BrowserPage>(), + box_value(e.Arguments())); + } + Window::Current().Activate(); + } + } +} + +void App::OnSuspending([[maybe_unused]] IInspectable const &sender, + [[maybe_unused]] SuspendingEventArgs const &e) {} + +void App::OnNavigationFailed(IInspectable const &, + NavigationFailedEventArgs const &e) { + throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + + e.SourcePageType().Name); +} diff --git a/support/hololens/ServoApp/App.h b/support/hololens/ServoApp/App.h new file mode 100644 index 00000000000..b372c5b7759 --- /dev/null +++ b/support/hololens/ServoApp/App.h @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once +#include "App.xaml.g.h" + +namespace winrt::ServoApp::implementation { +struct App : AppT<App> { + App(); + + void OnLaunched( + Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const &); + void OnSuspending(IInspectable const &, + Windows::ApplicationModel::SuspendingEventArgs const &); + void OnNavigationFailed( + IInspectable const &, + Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const &); +}; +} // namespace winrt::ServoApp::implementation diff --git a/support/hololens/ServoApp/App.idl b/support/hololens/ServoApp/App.idl new file mode 100644 index 00000000000..f72eff58eb1 --- /dev/null +++ b/support/hololens/ServoApp/App.idl @@ -0,0 +1,3 @@ +namespace ServoApp +{ +} diff --git a/support/hololens/ServoApp/App.xaml b/support/hololens/ServoApp/App.xaml new file mode 100644 index 00000000000..015f637b3df --- /dev/null +++ b/support/hololens/ServoApp/App.xaml @@ -0,0 +1,7 @@ +<Application + x:Class="ServoApp.App" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="using:ServoApp"> + +</Application> diff --git a/support/hololens/ServoApp/Assets/LockScreenLogo.scale-200.png b/support/hololens/ServoApp/Assets/LockScreenLogo.scale-200.png Binary files differnew file mode 100644 index 00000000000..735f57adb5d --- /dev/null +++ b/support/hololens/ServoApp/Assets/LockScreenLogo.scale-200.png diff --git a/support/hololens/ServoApp/Assets/SplashScreen.scale-200.png b/support/hololens/ServoApp/Assets/SplashScreen.scale-200.png Binary files differnew file mode 100644 index 00000000000..023e7f1feda --- /dev/null +++ b/support/hololens/ServoApp/Assets/SplashScreen.scale-200.png diff --git a/support/hololens/ServoApp/Assets/Square150x150Logo.scale-200.png b/support/hololens/ServoApp/Assets/Square150x150Logo.scale-200.png Binary files differnew file mode 100644 index 00000000000..af49fec1a54 --- /dev/null +++ b/support/hololens/ServoApp/Assets/Square150x150Logo.scale-200.png diff --git a/support/hololens/ServoApp/Assets/Square44x44Logo.scale-200.png b/support/hololens/ServoApp/Assets/Square44x44Logo.scale-200.png Binary files differnew file mode 100644 index 00000000000..ce342a2ec8a --- /dev/null +++ b/support/hololens/ServoApp/Assets/Square44x44Logo.scale-200.png diff --git a/support/hololens/ServoApp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/support/hololens/ServoApp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png Binary files differnew file mode 100644 index 00000000000..f6c02ce97e0 --- /dev/null +++ b/support/hololens/ServoApp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png diff --git a/support/hololens/ServoApp/Assets/StoreLogo.png b/support/hololens/ServoApp/Assets/StoreLogo.png Binary files differnew file mode 100644 index 00000000000..7385b56c0e4 --- /dev/null +++ b/support/hololens/ServoApp/Assets/StoreLogo.png diff --git a/support/hololens/ServoApp/Assets/Wide310x150Logo.scale-200.png b/support/hololens/ServoApp/Assets/Wide310x150Logo.scale-200.png Binary files differnew file mode 100644 index 00000000000..288995b397f --- /dev/null +++ b/support/hololens/ServoApp/Assets/Wide310x150Logo.scale-200.png diff --git a/support/hololens/ServoApp/BrowserPage.cpp b/support/hololens/ServoApp/BrowserPage.cpp new file mode 100644 index 00000000000..6130574aaef --- /dev/null +++ b/support/hololens/ServoApp/BrowserPage.cpp @@ -0,0 +1,236 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "pch.h" +#include "logs.h" +#include "BrowserPage.h" +#include "BrowserPage.g.cpp" +#include "ImmersiveView.h" +#include "OpenGLES.h" + +using namespace std::placeholders; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::UI::ViewManagement; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Graphics::Holographic; +using namespace concurrency; + +static char sWakeupEvent[] = "SIGNAL_WAKEUP"; + +namespace winrt::ServoApp::implementation { +BrowserPage::BrowserPage() { + InitializeComponent(); + log("BrowserPage::BrowserPage()"); + Loaded(std::bind(&BrowserPage::OnPageLoaded, this, _1, _2)); + Window::Current().CoreWindow().VisibilityChanged( + std::bind(&BrowserPage::OnVisibilityChanged, this, _1, _2)); +} + +void BrowserPage::OnPageLoaded(IInspectable const &, RoutedEventArgs const &) { + log("BrowserPage::OnPageLoaded()"); + CreateRenderSurface(); + StartRenderLoop(); + + swapChainPanel().PointerReleased( + std::bind(&BrowserPage::OnSurfaceClicked, this, _1, _2)); +} + +void BrowserPage::OnSurfaceClicked(IInspectable const &, + Input::PointerRoutedEventArgs const &e) { + auto coords = e.GetCurrentPoint(swapChainPanel()); + auto x = coords.Position().X; + auto y = coords.Position().Y; + + SendEventToServo({{Event::CLICK}, {x, y}}); + + e.Handled(true); +} + +void BrowserPage::SendEventToServo(Event event) { + mEventsMutex.lock(); + mEvents.push_back(event); + mEventsMutex.unlock(); + Servo::sWakeUp(); +} + +void BrowserPage::OnBackButtonClicked(IInspectable const &, + RoutedEventArgs const &) { + SendEventToServo({{Event::BACK}}); +} + +void BrowserPage::OnForwardButtonClicked(IInspectable const &, + RoutedEventArgs const &) { + SendEventToServo({{Event::FORWARD}}); +} +void BrowserPage::OnImmersiveButtonClicked(IInspectable const &, + RoutedEventArgs const &) { + if (HolographicSpace::IsAvailable()) { + log("Holographic space available"); + auto v = + winrt::Windows::ApplicationModel::Core::CoreApplication::CreateNewView( + mImmersiveViewSource); + auto parentId = ApplicationView::GetForCurrentView().Id(); + v.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [=]() { + auto winId = ApplicationView::GetForCurrentView().Id(); + ApplicationViewSwitcher::SwitchAsync(winId, parentId); + log("Immersive view started"); + }); + } else { + log("Holographic space not available"); + } +} + +void BrowserPage::OnVisibilityChanged(CoreWindow const &, + VisibilityChangedEventArgs const &args) { + auto visible = args.Visible(); + if (visible && !IsLoopRunning()) { + StartRenderLoop(); + } + if (!visible && IsLoopRunning()) { + StopRenderLoop(); + } +} + +void BrowserPage::CreateRenderSurface() { + if (mRenderSurface == EGL_NO_SURFACE) { + mRenderSurface = mOpenGLES.CreateSurface(swapChainPanel()); + } +} + +void BrowserPage::DestroyRenderSurface() { + mOpenGLES.DestroySurface(mRenderSurface); + mRenderSurface = EGL_NO_SURFACE; +} + +void BrowserPage::RecoverFromLostDevice() { + StopRenderLoop(); + DestroyRenderSurface(); + mOpenGLES.Reset(); + CreateRenderSurface(); + StartRenderLoop(); +} + +bool BrowserPage::IsLoopRunning() { + return mLoopTask != nullptr && !mLoopTask->is_done(); +} + +void BrowserPage::Loop(cancellation_token cancel) { + log("BrowserPage::Loop(). GL thread: %i", GetCurrentThreadId()); + + HANDLE hEvent = ::CreateEventA(nullptr, FALSE, FALSE, sWakeupEvent); + + Servo::sOnAlert = [=](std::wstring message) { + // FIXME: make this sync + swapChainPanel().Dispatcher().RunAsync( + Windows::UI::Core::CoreDispatcherPriority::High, [=]() { + Windows::UI::Popups::MessageDialog msg{message}; + msg.ShowAsync(); + }); + }; + + Servo::sOnTitleChanged = [=](std::wstring title) { + swapChainPanel().Dispatcher().RunAsync(CoreDispatcherPriority::High, [=]() { + ApplicationView::GetForCurrentView().Title(title); + }); + }; + + Servo::sOnURLChanged = [=](std::wstring url) { + swapChainPanel().Dispatcher().RunAsync(CoreDispatcherPriority::High, + [=]() { urlTextbox().Text(url); }); + }; + + Servo::sMakeCurrent = [=]() { + /* EGLint panelWidth = 0; */ + /* EGLint panelHeight = 0; */ + /* mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, + * &panelHeight); */ + /* glViewport(0, 0, panelWidth, panelHeight); */ + /* mServo->SetSize(panelWidth, panelHeight); */ + mOpenGLES.MakeCurrent(mRenderSurface); + }; + + Servo::sFlush = [=]() { + if (mOpenGLES.SwapBuffers(mRenderSurface) != GL_TRUE) { + // The call to eglSwapBuffers might not be successful (i.e. due to Device + // Lost) If the call fails, then we must reinitialize EGL and the GL + // resources. + swapChainPanel().Dispatcher().RunAsync( + CoreDispatcherPriority::High, [this]() { RecoverFromLostDevice(); }); + } + }; + + mOpenGLES.MakeCurrent(mRenderSurface); + + EGLint panelWidth = 0; + EGLint panelHeight = 0; + mOpenGLES.GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); + glViewport(0, 0, panelWidth, panelHeight); + mServo = std::make_unique<Servo>(panelWidth, panelHeight); + + // mServo->SetBatchMode(true); + // FIXME: ^ this should be necessary as call perform_update + // ourself. But enabling batch mode will make clicking a link + // not working because during the click, this thread is not + // waiting on the hEvent object. See the "wakeup" comment. + + while (!cancel.is_canceled()) { + // Block until Servo::sWakeUp is called. + // Or run full speed if animating (see on_animating_changed), + // it will endup blocking on SwapBuffers to limit rendering to 60FPS + if (!Servo::sAnimating) { + ::WaitForSingleObject(hEvent, INFINITE); + } + mEventsMutex.lock(); + for (auto &&e : mEvents) { + switch (e.type) { + case Event::CLICK: { + auto [x, y] = e.coords; + mServo->Click(x, y); + break; + } + case Event::FORWARD: + mServo->GoForward(); + break; + case Event::BACK: + mServo->GoBack(); + break; + } + } + mEvents.clear(); + mEventsMutex.unlock(); + mServo->PerformUpdates(); + } + cancel_current_task(); +} + +void BrowserPage::StartRenderLoop() { + if (IsLoopRunning()) { + return; + } + + auto token = mLoopCancel.get_token(); + + Servo::sWakeUp = []() { + // FIXME: this won't work if it's triggered while the thread is not + // waiting. We need a better looping logic. + HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, FALSE, sWakeupEvent); + ::SetEvent(hEvent); + }; + + log("BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId()); + + mLoopTask = std::make_unique<Concurrency::task<void>>( + Concurrency::create_task([=] { Loop(token); }, token)); +} + +void BrowserPage::StopRenderLoop() { + if (IsLoopRunning()) { + mLoopCancel.cancel(); + mLoopTask->wait(); + mLoopTask.reset(); + } +} + +} // namespace winrt::ServoApp::implementation diff --git a/support/hololens/ServoApp/BrowserPage.h b/support/hololens/ServoApp/BrowserPage.h new file mode 100644 index 00000000000..89e5248722f --- /dev/null +++ b/support/hololens/ServoApp/BrowserPage.h @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once + +#include "BrowserPage.g.h" +#include "ImmersiveView.h" +#include "OpenGLES.h" +#include "Servo.h" + +namespace winrt::ServoApp::implementation { + +struct Event { + enum { CLICK, BACK, FORWARD } type; + std::tuple<float, float> coords; +}; + +struct BrowserPage : BrowserPageT<BrowserPage> { +public: + BrowserPage(); + + void OnImmersiveButtonClicked(Windows::Foundation::IInspectable const &, + Windows::UI::Xaml::RoutedEventArgs const &); + void OnForwardButtonClicked(Windows::Foundation::IInspectable const &, + Windows::UI::Xaml::RoutedEventArgs const &); + void OnBackButtonClicked(Windows::Foundation::IInspectable const &, + Windows::UI::Xaml::RoutedEventArgs const &); + + void + OnSurfaceClicked(Windows::Foundation::IInspectable const &, + Windows::UI::Xaml::Input::PointerRoutedEventArgs const &); + +private: + void OnVisibilityChanged( + Windows::UI::Core::CoreWindow const &, + Windows::UI::Core::VisibilityChangedEventArgs const &args); + void OnPageLoaded(Windows::Foundation::IInspectable const &, + Windows::UI::Xaml::RoutedEventArgs const &); + + void CreateRenderSurface(); + void DestroyRenderSurface(); + void RecoverFromLostDevice(); + + void StartRenderLoop(); + void StopRenderLoop(); + void Loop(Concurrency::cancellation_token); + bool IsLoopRunning(); + + Concurrency::cancellation_token_source mLoopCancel; + std::unique_ptr<Concurrency::task<void>> mLoopTask; + winrt::ServoApp::ImmersiveViewSource mImmersiveViewSource; + EGLSurface mRenderSurface{EGL_NO_SURFACE}; + std::unique_ptr<Servo> mServo; + + void BrowserPage::SendEventToServo(Event event); + std::vector<Event> mEvents; + std::mutex mEventsMutex; + + OpenGLES mOpenGLES; // FIXME: shared pointer +}; +} // namespace winrt::ServoApp::implementation + +namespace winrt::ServoApp::factory_implementation { +struct BrowserPage : BrowserPageT<BrowserPage, implementation::BrowserPage> {}; +} // namespace winrt::ServoApp::factory_implementation diff --git a/support/hololens/ServoApp/BrowserPage.idl b/support/hololens/ServoApp/BrowserPage.idl new file mode 100644 index 00000000000..47de6a4ed66 --- /dev/null +++ b/support/hololens/ServoApp/BrowserPage.idl @@ -0,0 +1,8 @@ +namespace ServoApp +{ + [default_interface] + runtimeclass BrowserPage : Windows.UI.Xaml.Controls.Page + { + BrowserPage(); + } +} diff --git a/support/hololens/ServoApp/BrowserPage.xaml b/support/hololens/ServoApp/BrowserPage.xaml new file mode 100644 index 00000000000..bd1f88d8f5a --- /dev/null +++ b/support/hololens/ServoApp/BrowserPage.xaml @@ -0,0 +1,34 @@ +<Page + x:Class="ServoApp.BrowserPage" + x:Name="browserPage" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="using:ServoApp" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d"> + + <Grid VerticalAlignment="Stretch"> + <Grid.RowDefinitions> + <RowDefinition Height="auto"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <Grid Grid.Row="0"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="auto"/> + <ColumnDefinition Width="*"/> + <ColumnDefinition Width="auto"/> + </Grid.ColumnDefinitions> + <StackPanel Orientation="Horizontal" Grid.Column="0"> + <Button Content="Back" Click="OnBackButtonClicked"/> + <Button Content="Forward" Click="OnForwardButtonClicked"/> + </StackPanel> + <TextBox Text="" AcceptsReturn="True" PlaceholderText="Type a URL" x:Name="urlTextbox" Grid.Column="1" IsReadOnly="True"/> + <StackPanel Orientation="Horizontal" Grid.Column="2"> + <Button x:Name="immersiveButton" Click="OnImmersiveButtonClicked">Run Immersive</Button> + </StackPanel> + </Grid> + <SwapChainPanel x:Name="swapChainPanel" MinHeight="200" MinWidth="200" Grid.Row="1"> + </SwapChainPanel> + </Grid> +</Page> diff --git a/support/hololens/ServoApp/Common/CameraResources.cpp b/support/hololens/ServoApp/Common/CameraResources.cpp new file mode 100644 index 00000000000..4391a55c74e --- /dev/null +++ b/support/hololens/ServoApp/Common/CameraResources.cpp @@ -0,0 +1,234 @@ +#include "pch.h" + +#include "CameraResources.h" +#include "Common/DirectXHelper.h" +#include "DeviceResources.h" + +using namespace DirectX; +using namespace Microsoft::WRL; +using namespace winrt::Windows::Foundation::Numerics; +using namespace winrt::Windows::Graphics::DirectX::Direct3D11; +using namespace winrt::Windows::Graphics::Holographic; +using namespace winrt::Windows::Perception::Spatial; + +DX::CameraResources::CameraResources(HolographicCamera const &camera) + : m_holographicCamera(camera), m_isStereo(camera.IsStereo()), + m_d3dRenderTargetSize(camera.RenderTargetSize()) { + m_d3dViewport = CD3D11_VIEWPORT(0.f, 0.f, m_d3dRenderTargetSize.Width, + m_d3dRenderTargetSize.Height); +}; + +// Updates resources associated with a holographic camera's swap chain. +// The app does not access the swap chain directly, but it does create +// resource views for the back buffer. +void DX::CameraResources::CreateResourcesForBackBuffer( + DX::DeviceResources *pDeviceResources, + HolographicCameraRenderingParameters const &cameraParameters) { + ID3D11Device *device = pDeviceResources->GetD3DDevice(); + + // Get the WinRT object representing the holographic camera's back buffer. + IDirect3DSurface surface = cameraParameters.Direct3D11BackBuffer(); + + // Get the holographic camera's back buffer. + // Holographic apps do not create a swap chain themselves; instead, buffers + // are owned by the system. The Direct3D back buffer resources are provided to + // the app using WinRT interop APIs. + ComPtr<ID3D11Texture2D> cameraBackBuffer; + winrt::check_hresult(surface + .as<::Windows::Graphics::DirectX::Direct3D11:: + IDirect3DDxgiInterfaceAccess>() + ->GetInterface(IID_PPV_ARGS(&cameraBackBuffer))); + + // Determine if the back buffer has changed. If so, ensure that the render + // target view is for the current back buffer. + if (m_d3dBackBuffer.Get() != cameraBackBuffer.Get()) { + // This can change every frame as the system moves to the next buffer in the + // swap chain. This mode of operation will occur when certain rendering + // modes are activated. + m_d3dBackBuffer = cameraBackBuffer; + + // Create a render target view of the back buffer. + // Creating this resource is inexpensive, and is better than keeping track + // of the back buffers in order to pre-allocate render target views for each + // one. + winrt::check_hresult(device->CreateRenderTargetView( + m_d3dBackBuffer.Get(), nullptr, &m_d3dRenderTargetView)); + + // Get the DXGI format for the back buffer. + // This information can be accessed by the app using + // CameraResources::GetBackBufferDXGIFormat(). + D3D11_TEXTURE2D_DESC backBufferDesc; + m_d3dBackBuffer->GetDesc(&backBufferDesc); + m_dxgiFormat = backBufferDesc.Format; + + // Check for render target size changes. + winrt::Windows::Foundation::Size currentSize = + m_holographicCamera.RenderTargetSize(); + if (m_d3dRenderTargetSize != currentSize) { + // Set render target size. + m_d3dRenderTargetSize = currentSize; + + // A new depth stencil view is also needed. + m_d3dDepthStencilView.Reset(); + } + } + + // Refresh depth stencil resources, if needed. + if (m_d3dDepthStencilView == nullptr) { + // Create a depth stencil view for use with 3D rendering if needed. + CD3D11_TEXTURE2D_DESC depthStencilDesc( + DXGI_FORMAT_R16_TYPELESS, + static_cast<UINT>(m_d3dRenderTargetSize.Width), + static_cast<UINT>(m_d3dRenderTargetSize.Height), + m_isStereo ? 2 : 1, // Create two textures when rendering in stereo. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE); + + winrt::check_hresult(device->CreateTexture2D(&depthStencilDesc, nullptr, + &m_d3dDepthStencil)); + + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc( + m_isStereo ? D3D11_DSV_DIMENSION_TEXTURE2DARRAY + : D3D11_DSV_DIMENSION_TEXTURE2D, + DXGI_FORMAT_D16_UNORM); + winrt::check_hresult(device->CreateDepthStencilView( + m_d3dDepthStencil.Get(), &depthStencilViewDesc, + &m_d3dDepthStencilView)); + } + + // Create the constant buffer, if needed. + if (m_viewProjectionConstantBuffer == nullptr) { + // Create a constant buffer to store view and projection matrices for the + // camera. + CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ViewProjectionConstantBuffer), + D3D11_BIND_CONSTANT_BUFFER); + winrt::check_hresult(device->CreateBuffer(&constantBufferDesc, nullptr, + &m_viewProjectionConstantBuffer)); + } +} + +// Releases resources associated with a back buffer. +void DX::CameraResources::ReleaseResourcesForBackBuffer( + DX::DeviceResources *pDeviceResources) { + ID3D11DeviceContext *context = pDeviceResources->GetD3DDeviceContext(); + + // Release camera-specific resources. + m_d3dBackBuffer.Reset(); + m_d3dDepthStencil.Reset(); + m_d3dRenderTargetView.Reset(); + m_d3dDepthStencilView.Reset(); + m_viewProjectionConstantBuffer.Reset(); + + // Ensure system references to the back buffer are released by clearing the + // render target from the graphics pipeline state, and then flushing the + // Direct3D context. + ID3D11RenderTargetView *nullViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = { + nullptr}; + context->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr); + context->Flush(); +} + +// Updates the view/projection constant buffer for a holographic camera. +void DX::CameraResources::UpdateViewProjectionBuffer( + std::shared_ptr<DX::DeviceResources> deviceResources, + HolographicCameraPose const &cameraPose, + SpatialCoordinateSystem const &coordinateSystem) { + // The system changes the viewport on a per-frame basis for system + // optimizations. + auto viewport = cameraPose.Viewport(); + m_d3dViewport = + CD3D11_VIEWPORT(viewport.X, viewport.Y, viewport.Width, viewport.Height); + + // The projection transform for each frame is provided by the + // HolographicCameraPose. + HolographicStereoTransform cameraProjectionTransform = + cameraPose.ProjectionTransform(); + + // Get a container object with the view and projection matrices for the given + // pose in the given coordinate system. + auto viewTransformContainer = + cameraPose.TryGetViewTransform(coordinateSystem); + + // If TryGetViewTransform returns a null pointer, that means the pose and + // coordinate system cannot be understood relative to one another; content + // cannot be rendered in this coordinate system for the duration of the + // current frame. This usually means that positional tracking is not active + // for the current frame, in which case it is possible to use a + // SpatialLocatorAttachedFrameOfReference to render content that is not + // world-locked instead. + DX::ViewProjectionConstantBuffer viewProjectionConstantBufferData; + bool viewTransformAcquired = viewTransformContainer != nullptr; + if (viewTransformAcquired) { + // Otherwise, the set of view transforms can be retrieved. + HolographicStereoTransform viewCoordinateSystemTransform = + viewTransformContainer.Value(); + + // Update the view matrices. Holographic cameras (such as Microsoft + // HoloLens) are constantly moving relative to the world. The view matrices + // need to be updated every frame. + XMStoreFloat4x4( + &viewProjectionConstantBufferData.viewProjection[0], + XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Left) * + XMLoadFloat4x4(&cameraProjectionTransform.Left))); + XMStoreFloat4x4( + &viewProjectionConstantBufferData.viewProjection[1], + XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Right) * + XMLoadFloat4x4(&cameraProjectionTransform.Right))); + } + + // Use the D3D device context to update Direct3D device-based resources. + ID3D11DeviceContext *context = deviceResources->GetD3DDeviceContext(); + + // Loading is asynchronous. Resources must be created before they can be + // updated. + if (context == nullptr || m_viewProjectionConstantBuffer == nullptr || + !viewTransformAcquired) { + m_framePending = false; + } else { + // Update the view and projection matrices. + context->UpdateSubresource(m_viewProjectionConstantBuffer.Get(), 0, nullptr, + &viewProjectionConstantBufferData, 0, 0); + + m_framePending = true; + } +} + +// Gets the view-projection constant buffer for the HolographicCamera and +// attaches it to the shader pipeline. +bool DX::CameraResources::AttachViewProjectionBuffer( + std::shared_ptr<DX::DeviceResources> &deviceResources) { + // This method uses Direct3D device-based resources. + ID3D11DeviceContext *context = deviceResources->GetD3DDeviceContext(); + + // Loading is asynchronous. Resources must be created before they can be + // updated. Cameras can also be added asynchronously, in which case they must + // be initialized before they can be used. + if (context == nullptr || m_viewProjectionConstantBuffer == nullptr || + m_framePending == false) { + return false; + } + + // Set the viewport for this camera. + context->RSSetViewports(1, &m_d3dViewport); + + // Send the constant buffer to the vertex shader. + context->VSSetConstantBuffers(1, 1, + m_viewProjectionConstantBuffer.GetAddressOf()); + + // The template includes a pass-through geometry shader that is used by + // default on systems that don't support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer extension. The shader + // will be enabled at run-time on systems that require it. + // If your app will also use the geometry shader for other tasks and those + // tasks require the view/projection matrix, uncomment the following line + // of code to send the constant buffer to the geometry shader as well. + /*context->GSSetConstantBuffers( + 1, + 1, + m_viewProjectionConstantBuffer.GetAddressOf() + );*/ + + m_framePending = false; + + return true; +} diff --git a/support/hololens/ServoApp/Common/CameraResources.h b/support/hololens/ServoApp/Common/CameraResources.h new file mode 100644 index 00000000000..14e78758d71 --- /dev/null +++ b/support/hololens/ServoApp/Common/CameraResources.h @@ -0,0 +1,93 @@ +#pragma once + +namespace DX { +class DeviceResources; + +// Constant buffer used to send the view-projection matrices to the shader +// pipeline. +struct ViewProjectionConstantBuffer { + DirectX::XMFLOAT4X4 viewProjection[2]; +}; + +// Assert that the constant buffer remains 16-byte aligned (best practice). +static_assert((sizeof(ViewProjectionConstantBuffer) % (sizeof(float) * 4)) == 0, + "ViewProjection constant buffer size must be 16-byte aligned (16 " + "bytes is the length of four floats)."); + +// Manages DirectX device resources that are specific to a holographic camera, +// such as the back buffer, ViewProjection constant buffer, and viewport. +class CameraResources { +public: + CameraResources(winrt::Windows::Graphics::Holographic::HolographicCamera const + &holographicCamera); + + void CreateResourcesForBackBuffer( + DX::DeviceResources *pDeviceResources, + winrt::Windows::Graphics::Holographic:: + HolographicCameraRenderingParameters const &cameraParameters); + void ReleaseResourcesForBackBuffer(DX::DeviceResources *pDeviceResources); + + void UpdateViewProjectionBuffer( + std::shared_ptr<DX::DeviceResources> deviceResources, + winrt::Windows::Graphics::Holographic::HolographicCameraPose const + &cameraPose, + winrt::Windows::Perception::Spatial::SpatialCoordinateSystem const + &coordinateSystem); + + bool AttachViewProjectionBuffer( + std::shared_ptr<DX::DeviceResources> &deviceResources); + + // Direct3D device resources. + ID3D11RenderTargetView *GetBackBufferRenderTargetView() const { + return m_d3dRenderTargetView.Get(); + } + ID3D11DepthStencilView *GetDepthStencilView() const { + return m_d3dDepthStencilView.Get(); + } + ID3D11Texture2D *GetBackBufferTexture2D() const { + return m_d3dBackBuffer.Get(); + } + ID3D11Texture2D *GetDepthStencilTexture2D() const { + return m_d3dDepthStencil.Get(); + } + D3D11_VIEWPORT GetViewport() const { return m_d3dViewport; } + DXGI_FORMAT GetBackBufferDXGIFormat() const { return m_dxgiFormat; } + + // Render target properties. + winrt::Windows::Foundation::Size GetRenderTargetSize() const & { + return m_d3dRenderTargetSize; + } + bool IsRenderingStereoscopic() const { return m_isStereo; } + + // The holographic camera these resources are for. + winrt::Windows::Graphics::Holographic::HolographicCamera const & + GetHolographicCamera() const { + return m_holographicCamera; + } + +private: + // Direct3D rendering objects. Required for 3D. + Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_d3dRenderTargetView; + Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_d3dDepthStencilView; + Microsoft::WRL::ComPtr<ID3D11Texture2D> m_d3dBackBuffer; + Microsoft::WRL::ComPtr<ID3D11Texture2D> m_d3dDepthStencil; + + // Device resource to store view and projection matrices. + Microsoft::WRL::ComPtr<ID3D11Buffer> m_viewProjectionConstantBuffer; + + // Direct3D rendering properties. + DXGI_FORMAT m_dxgiFormat; + winrt::Windows::Foundation::Size m_d3dRenderTargetSize; + D3D11_VIEWPORT m_d3dViewport; + + // Indicates whether the camera supports stereoscopic rendering. + bool m_isStereo = false; + + // Indicates whether this camera has a pending frame. + bool m_framePending = false; + + // Pointer to the holographic camera these resources are for. + winrt::Windows::Graphics::Holographic::HolographicCamera m_holographicCamera = + nullptr; +}; +} // namespace DX diff --git a/support/hololens/ServoApp/Common/DeviceResources.cpp b/support/hololens/ServoApp/Common/DeviceResources.cpp new file mode 100644 index 00000000000..f5ffbec0d89 --- /dev/null +++ b/support/hololens/ServoApp/Common/DeviceResources.cpp @@ -0,0 +1,280 @@ + +#include "pch.h" +#include "DeviceResources.h" +#include "DirectXHelper.h" + +using namespace D2D1; +using namespace Microsoft::WRL; +using namespace winrt::Windows::Graphics::DirectX::Direct3D11; +using namespace winrt::Windows::Graphics::Display; +using namespace winrt::Windows::Graphics::Holographic; + +// Constructor for DeviceResources. +DX::DeviceResources::DeviceResources() { CreateDeviceIndependentResources(); } + +// Configures resources that don't depend on the Direct3D device. +void DX::DeviceResources::CreateDeviceIndependentResources() { + // Initialize Direct2D resources. + D2D1_FACTORY_OPTIONS options{}; + +#if defined(_DEBUG) + // If the project is in a debug build, enable Direct2D debugging via SDK + // Layers. + options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; +#endif + + // Initialize the Direct2D Factory. + winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory2), &options, + &m_d2dFactory)); + + // Initialize the DirectWrite Factory. + winrt::check_hresult(DWriteCreateFactory( + DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &m_dwriteFactory)); + + // Initialize the Windows Imaging Component (WIC) Factory. + winrt::check_hresult(CoCreateInstance(CLSID_WICImagingFactory2, nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&m_wicFactory))); +} + +void DX::DeviceResources::SetHolographicSpace( + HolographicSpace holographicSpace) { + // Cache the holographic space. Used to re-initalize during device-lost + // scenarios. + m_holographicSpace = holographicSpace; + + InitializeUsingHolographicSpace(); +} + +void DX::DeviceResources::InitializeUsingHolographicSpace() { + // The holographic space might need to determine which adapter supports + // holograms, in which case it will specify a non-zero PrimaryAdapterId. + LUID id = {m_holographicSpace.PrimaryAdapterId().LowPart, + m_holographicSpace.PrimaryAdapterId().HighPart}; + + // When a primary adapter ID is given to the app, the app should find + // the corresponding DXGI adapter and use it to create Direct3D devices + // and device contexts. Otherwise, there is no restriction on the DXGI + // adapter the app can use. + if ((id.HighPart != 0) || (id.LowPart != 0)) { + UINT createFlags = 0; +#ifdef DEBUG + if (DX::SdkLayersAvailable()) { + createFlags |= DXGI_CREATE_FACTORY_DEBUG; + } +#endif + // Create the DXGI factory. + ComPtr<IDXGIFactory1> dxgiFactory; + winrt::check_hresult( + CreateDXGIFactory2(createFlags, IID_PPV_ARGS(&dxgiFactory))); + ComPtr<IDXGIFactory4> dxgiFactory4; + winrt::check_hresult(dxgiFactory.As(&dxgiFactory4)); + + // Retrieve the adapter specified by the holographic space. + winrt::check_hresult( + dxgiFactory4->EnumAdapterByLuid(id, IID_PPV_ARGS(&m_dxgiAdapter))); + } else { + m_dxgiAdapter.Reset(); + } + + CreateDeviceResources(); + + m_holographicSpace.SetDirect3D11Device(m_d3dInteropDevice); +} + +// Configures the Direct3D device, and stores handles to it and the device +// context. +void DX::DeviceResources::CreateDeviceResources() { + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(_DEBUG) + if (DX::SdkLayersAvailable()) { + // If the project is in a debug build, enable debugging via SDK Layers with + // this flag. + creationFlags |= D3D11_CREATE_DEVICE_DEBUG; + } +#endif + + // This array defines the set of DirectX hardware feature levels this app will + // support. Note the ordering should be preserved. Note that HoloLens supports + // feature level 11.1. The HoloLens emulator is also capable of running on + // graphics cards starting with feature level 10.0. + D3D_FEATURE_LEVEL featureLevels[] = { + D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0}; + + // Create the Direct3D 11 API device object and a corresponding context. + ComPtr<ID3D11Device> device; + ComPtr<ID3D11DeviceContext> context; + + const D3D_DRIVER_TYPE driverType = m_dxgiAdapter == nullptr + ? D3D_DRIVER_TYPE_HARDWARE + : D3D_DRIVER_TYPE_UNKNOWN; + const HRESULT hr = D3D11CreateDevice( + m_dxgiAdapter.Get(), // Either nullptr, or the primary adapter determined + // by Windows Holographic. + driverType, // Create a device using the hardware graphics driver. + 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. + creationFlags, // Set debug and Direct2D compatibility flags. + featureLevels, // List of feature levels this app can support. + ARRAYSIZE(featureLevels), // Size of the list above. + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows + // Runtime apps. + &device, // Returns the Direct3D device created. + &m_d3dFeatureLevel, // Returns feature level of device created. + &context // Returns the device immediate context. + ); + + if (FAILED(hr)) { + // If the initialization fails, fall back to the WARP device. + // For more information on WARP, see: + // http://go.microsoft.com/fwlink/?LinkId=286690 + winrt::check_hresult(D3D11CreateDevice( + nullptr, // Use the default DXGI adapter for WARP. + D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware + // device. + 0, creationFlags, featureLevels, ARRAYSIZE(featureLevels), + D3D11_SDK_VERSION, &device, &m_d3dFeatureLevel, &context)); + } + + // Store pointers to the Direct3D device and immediate context. + winrt::check_hresult(device.As(&m_d3dDevice)); + winrt::check_hresult(context.As(&m_d3dContext)); + + // Acquire the DXGI interface for the Direct3D device. + ComPtr<IDXGIDevice3> dxgiDevice; + winrt::check_hresult(m_d3dDevice.As(&dxgiDevice)); + + // Wrap the native device using a WinRT interop object. + winrt::com_ptr<::IInspectable> object; + winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice( + dxgiDevice.Get(), + reinterpret_cast<IInspectable **>(winrt::put_abi(object)))); + m_d3dInteropDevice = object.as<IDirect3DDevice>(); + + // Cache the DXGI adapter. + // This is for the case of no preferred DXGI adapter, or fallback to WARP. + ComPtr<IDXGIAdapter> dxgiAdapter; + winrt::check_hresult(dxgiDevice->GetAdapter(&dxgiAdapter)); + winrt::check_hresult(dxgiAdapter.As(&m_dxgiAdapter)); + + // Check for device support for the optional feature that allows setting the + // render target array index from the vertex shader stage. + D3D11_FEATURE_DATA_D3D11_OPTIONS3 options; + m_d3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &options, + sizeof(options)); + if (options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer) { + m_supportsVprt = true; + } +} + +// Validates the back buffer for each HolographicCamera and recreates +// resources for back buffers that have changed. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::EnsureCameraResources( + HolographicFrame frame, HolographicFramePrediction prediction) { + UseHolographicCameraResources<void>( + [this, frame, + prediction](std::map<UINT32, std::unique_ptr<CameraResources>> + &cameraResourceMap) { + for (HolographicCameraPose const &cameraPose : + prediction.CameraPoses()) { + HolographicCameraRenderingParameters renderingParameters = + frame.GetRenderingParameters(cameraPose); + CameraResources *pCameraResources = + cameraResourceMap[cameraPose.HolographicCamera().Id()].get(); + + pCameraResources->CreateResourcesForBackBuffer(this, + renderingParameters); + } + }); +} + +// Prepares to allocate resources and adds resource views for a camera. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::AddHolographicCamera(HolographicCamera camera) { + UseHolographicCameraResources<void>( + [this, camera](std::map<UINT32, std::unique_ptr<CameraResources>> + &cameraResourceMap) { + cameraResourceMap[camera.Id()] = + std::make_unique<CameraResources>(camera); + }); +} + +// Deallocates resources for a camera and removes the camera from the set. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::RemoveHolographicCamera(HolographicCamera camera) { + UseHolographicCameraResources<void>( + [this, camera](std::map<UINT32, std::unique_ptr<CameraResources>> + &cameraResourceMap) { + CameraResources *pCameraResources = + cameraResourceMap[camera.Id()].get(); + + if (pCameraResources != nullptr) { + pCameraResources->ReleaseResourcesForBackBuffer(this); + cameraResourceMap.erase(camera.Id()); + } + }); +} + +// Recreate all device resources and set them back to the current state. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::HandleDeviceLost() { + if (m_deviceNotify != nullptr) { + m_deviceNotify->OnDeviceLost(); + } + + UseHolographicCameraResources<void>( + [this](std::map<UINT32, std::unique_ptr<CameraResources>> + &cameraResourceMap) { + for (auto &pair : cameraResourceMap) { + CameraResources *pCameraResources = pair.second.get(); + pCameraResources->ReleaseResourcesForBackBuffer(this); + } + }); + + InitializeUsingHolographicSpace(); + + if (m_deviceNotify != nullptr) { + m_deviceNotify->OnDeviceRestored(); + } +} + +// Register our DeviceNotify to be informed on device lost and creation. +void DX::DeviceResources::RegisterDeviceNotify( + DX::IDeviceNotify *deviceNotify) { + m_deviceNotify = deviceNotify; +} + +// Call this method when the app suspends. It provides a hint to the driver that +// the app is entering an idle state and that temporary buffers can be reclaimed +// for use by other apps. +void DX::DeviceResources::Trim() { + m_d3dContext->ClearState(); + + ComPtr<IDXGIDevice3> dxgiDevice; + winrt::check_hresult(m_d3dDevice.As(&dxgiDevice)); + dxgiDevice->Trim(); +} + +// Present the contents of the swap chain to the screen. +// Locks the set of holographic camera resources until the function exits. +void DX::DeviceResources::Present(HolographicFrame frame) { + // By default, this API waits for the frame to finish before it returns. + // Holographic apps should wait for the previous frame to finish before + // starting work on a new frame. This allows for better results from + // holographic frame predictions. + HolographicFramePresentResult presentResult = + frame.PresentUsingCurrentPrediction(); + + // The PresentUsingCurrentPrediction API will detect when the graphics device + // changes or becomes invalid. When this happens, it is considered a Direct3D + // device lost scenario. + if (presentResult == HolographicFramePresentResult::DeviceRemoved) { + // The Direct3D device, context, and resources should be recreated. + HandleDeviceLost(); + } +} diff --git a/support/hololens/ServoApp/Common/DeviceResources.h b/support/hololens/ServoApp/Common/DeviceResources.h new file mode 100644 index 00000000000..ff0248b221d --- /dev/null +++ b/support/hololens/ServoApp/Common/DeviceResources.h @@ -0,0 +1,119 @@ + +#pragma once + +#include "CameraResources.h" + +namespace DX { +// Provides an interface for an application that owns DeviceResources to be +// notified of the device being lost or created. +interface IDeviceNotify { + virtual void OnDeviceLost() = 0; + virtual void OnDeviceRestored() = 0; +}; + +// Creates and manages a Direct3D device and immediate context, Direct2D device +// and context (for debug), and the holographic swap chain. +class DeviceResources { +public: + DeviceResources(); + + // Public methods related to Direct3D devices. + void HandleDeviceLost(); + void RegisterDeviceNotify(IDeviceNotify *deviceNotify); + void Trim(); + void Present(winrt::Windows::Graphics::Holographic::HolographicFrame frame); + + // Public methods related to holographic devices. + void SetHolographicSpace( + winrt::Windows::Graphics::Holographic::HolographicSpace space); + void EnsureCameraResources( + winrt::Windows::Graphics::Holographic::HolographicFrame frame, + winrt::Windows::Graphics::Holographic::HolographicFramePrediction + prediction); + + void AddHolographicCamera( + winrt::Windows::Graphics::Holographic::HolographicCamera camera); + void RemoveHolographicCamera( + winrt::Windows::Graphics::Holographic::HolographicCamera camera); + + // Holographic accessors. + template <typename RetType, typename LCallback> + RetType UseHolographicCameraResources(LCallback const &callback); + + winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice + GetD3DInteropDevice() const { + return m_d3dInteropDevice; + } + + // D3D accessors. + ID3D11Device4 *GetD3DDevice() const { return m_d3dDevice.Get(); } + ID3D11DeviceContext3 *GetD3DDeviceContext() const { + return m_d3dContext.Get(); + } + D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } + bool GetDeviceSupportsVprt() const { return m_supportsVprt; } + + // DXGI acessors. + IDXGIAdapter3 *GetDXGIAdapter() const { return m_dxgiAdapter.Get(); } + + // D2D accessors. + ID2D1Factory2 *GetD2DFactory() const { return m_d2dFactory.Get(); } + IDWriteFactory2 *GetDWriteFactory() const { return m_dwriteFactory.Get(); } + IWICImagingFactory2 *GetWicImagingFactory() const { + return m_wicFactory.Get(); + } + +private: + // Private methods related to the Direct3D device, and resources based on that + // device. + void CreateDeviceIndependentResources(); + void InitializeUsingHolographicSpace(); + void CreateDeviceResources(); + + // Direct3D objects. + Microsoft::WRL::ComPtr<ID3D11Device4> m_d3dDevice; + Microsoft::WRL::ComPtr<ID3D11DeviceContext3> m_d3dContext; + Microsoft::WRL::ComPtr<IDXGIAdapter3> m_dxgiAdapter; + + // Direct3D interop objects. + winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice + m_d3dInteropDevice; + + // Direct2D factories. + Microsoft::WRL::ComPtr<ID2D1Factory2> m_d2dFactory; + Microsoft::WRL::ComPtr<IDWriteFactory2> m_dwriteFactory; + Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory; + + // The holographic space provides a preferred DXGI adapter ID. + winrt::Windows::Graphics::Holographic::HolographicSpace m_holographicSpace = + nullptr; + + // Properties of the Direct3D device currently in use. + D3D_FEATURE_LEVEL m_d3dFeatureLevel = D3D_FEATURE_LEVEL_10_0; + + // The IDeviceNotify can be held directly as it owns the DeviceResources. + IDeviceNotify *m_deviceNotify = nullptr; + + // Whether or not the current Direct3D device supports the optional feature + // for setting the render target array index from the vertex shader stage. + bool m_supportsVprt = false; + + // Back buffer resources, etc. for attached holographic cameras. + std::map<UINT32, std::unique_ptr<CameraResources>> m_cameraResources; + std::mutex m_cameraResourcesLock; +}; +} // namespace DX + +// Device-based resources for holographic cameras are stored in a std::map. +// Access this list by providing a callback to this function, and the std::map +// will be guarded from add and remove events until the callback returns. The +// callback is processed immediately and must not contain any nested calls to +// UseHolographicCameraResources. The callback takes a parameter of type +// std::map<UINT32, std::unique_ptr<DX::CameraResources>>& through which the +// list of cameras will be accessed. +template <typename RetType, typename LCallback> +RetType +DX::DeviceResources::UseHolographicCameraResources(LCallback const &callback) { + std::lock_guard<std::mutex> guard(m_cameraResourcesLock); + return callback(m_cameraResources); +} diff --git a/support/hololens/ServoApp/Common/DirectXHelper.h b/support/hololens/ServoApp/Common/DirectXHelper.h new file mode 100644 index 00000000000..5ab0dae02c7 --- /dev/null +++ b/support/hololens/ServoApp/Common/DirectXHelper.h @@ -0,0 +1,65 @@ +#pragma once + +namespace DX { +// Function that reads from a binary file asynchronously. +inline std::future<std::vector<byte>> +ReadDataAsync(const std::wstring_view &filename) { + using namespace winrt::Windows::Storage; + using namespace winrt::Windows::Storage::Streams; + + IBuffer fileBuffer = co_await PathIO::ReadBufferAsync(filename); + + std::vector<byte> returnBuffer; + returnBuffer.resize(fileBuffer.Length()); + DataReader::FromBuffer(fileBuffer) + .ReadBytes(winrt::array_view<uint8_t>(returnBuffer)); + return returnBuffer; +} + +// Converts a length in device-independent pixels (DIPs) to a length in physical +// pixels. +inline float ConvertDipsToPixels(float dips, float dpi) { + constexpr float dipsPerInch = 96.0f; + return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. +} + +inline winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface +CreateDepthTextureInteropObject( + const Microsoft::WRL::ComPtr<ID3D11Texture2D> spTexture2D) { + // Direct3D interop APIs are used to provide the buffer to the WinRT API. + Microsoft::WRL::ComPtr<IDXGIResource1> depthStencilResource; + winrt::check_hresult(spTexture2D.As(&depthStencilResource)); + Microsoft::WRL::ComPtr<IDXGISurface2> depthDxgiSurface; + winrt::check_hresult( + depthStencilResource->CreateSubresourceSurface(0, &depthDxgiSurface)); + winrt::com_ptr<::IInspectable> inspectableSurface; + winrt::check_hresult(CreateDirect3D11SurfaceFromDXGISurface( + depthDxgiSurface.Get(), + reinterpret_cast<IInspectable **>(winrt::put_abi(inspectableSurface)))); + + return inspectableSurface + .as<winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface>(); +} + +#if defined(_DEBUG) +// Check for SDK Layer support. +inline bool SdkLayersAvailable() { + HRESULT hr = D3D11CreateDevice( + nullptr, + D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware + // device. + 0, + D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr, // Any feature level will do. + 0, + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows + // Runtime apps. + nullptr, // No need to keep the D3D device reference. + nullptr, // No need to know the feature level. + nullptr // No need to keep the D3D device context reference. + ); + + return SUCCEEDED(hr); +} +#endif +} // namespace DX diff --git a/support/hololens/ServoApp/Common/StepTimer.h b/support/hololens/ServoApp/Common/StepTimer.h new file mode 100644 index 00000000000..36102d680db --- /dev/null +++ b/support/hololens/ServoApp/Common/StepTimer.h @@ -0,0 +1,179 @@ +#pragma once + +namespace DX { +// Helper class for animation and simulation timing. +class StepTimer { +public: + StepTimer() + : m_elapsedTicks(0), m_totalTicks(0), m_leftOverTicks(0), m_frameCount(0), + m_framesPerSecond(0), m_framesThisSecond(0), m_qpcSecondCounter(0), + m_isFixedTimeStep(false), m_targetElapsedTicks(TicksPerSecond / 60) { + m_qpcFrequency = GetPerformanceFrequency(); + + // Initialize max delta to 1/10 of a second. + m_qpcMaxDelta = m_qpcFrequency / 10; + } + + // Get elapsed time since the previous Update call. + uint64_t GetElapsedTicks() const { return m_elapsedTicks; } + double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } + + // Get total time since the start of the program. + uint64_t GetTotalTicks() const { return m_totalTicks; } + double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } + + // Get total number of updates since start of the program. + uint32_t GetFrameCount() const { return m_frameCount; } + + // Get the current framerate. + uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } + + // Set whether to use fixed or variable timestep mode. + void SetFixedTimeStep(bool isFixedTimestep) { + m_isFixedTimeStep = isFixedTimestep; + } + + // Set how often to call Update when in fixed timestep mode. + void SetTargetElapsedTicks(uint64_t targetElapsed) { + m_targetElapsedTicks = targetElapsed; + } + void SetTargetElapsedSeconds(double targetElapsed) { + m_targetElapsedTicks = SecondsToTicks(targetElapsed); + } + + // Integer format represents time using 10,000,000 ticks per second. + static const uint64_t TicksPerSecond = 10'000'000; + + static double TicksToSeconds(uint64_t ticks) { + return static_cast<double>(ticks) / TicksPerSecond; + } + static uint64_t SecondsToTicks(double seconds) { + return static_cast<uint64_t>(seconds * TicksPerSecond); + } + + // Convenient wrapper for QueryPerformanceFrequency. Throws an exception if + // the call to QueryPerformanceFrequency fails. + static inline uint64_t GetPerformanceFrequency() { + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq)) { + winrt::throw_last_error(); + } + return freq.QuadPart; + } + + // Gets the current number of ticks from QueryPerformanceCounter. Throws an + // exception if the call to QueryPerformanceCounter fails. + static inline int64_t GetTicks() { + LARGE_INTEGER ticks; + if (!QueryPerformanceCounter(&ticks)) { + winrt::throw_last_error(); + } + return ticks.QuadPart; + } + + // After an intentional timing discontinuity (for instance a blocking IO + // operation) call this to avoid having the fixed timestep logic attempt a set + // of catch-up Update calls. + + void ResetElapsedTime() { + m_qpcLastTime = GetTicks(); + + m_leftOverTicks = 0; + m_framesPerSecond = 0; + m_framesThisSecond = 0; + m_qpcSecondCounter = 0; + } + + // Update timer state, calling the specified Update function the appropriate + // number of times. + template <typename TUpdate> void Tick(const TUpdate &update) { + // Query the current time. + uint64_t currentTime = GetTicks(); + uint64_t timeDelta = currentTime - m_qpcLastTime; + + m_qpcLastTime = currentTime; + m_qpcSecondCounter += timeDelta; + + // Clamp excessively large time deltas (e.g. after paused in the debugger). + if (timeDelta > m_qpcMaxDelta) { + timeDelta = m_qpcMaxDelta; + } + + // Convert QPC units into a canonical tick format. This cannot overflow due + // to the previous clamp. + timeDelta *= TicksPerSecond; + timeDelta /= m_qpcFrequency; + + uint32_t lastFrameCount = m_frameCount; + + if (m_isFixedTimeStep) { + // Fixed timestep update logic + + // If the app is running very close to the target elapsed time (within 1/4 + // of a millisecond) just clamp the clock to exactly match the target + // value. This prevents tiny and irrelevant errors from accumulating over + // time. Without this clamping, a game that requested a 60 fps fixed + // update, running with vsync enabled on a 59.94 NTSC display, would + // eventually accumulate enough tiny errors that it would drop a frame. It + // is better to just round small deviations down to zero to leave things + // running smoothly. + + if (abs(static_cast<int64_t>(timeDelta - m_targetElapsedTicks)) < + TicksPerSecond / 4000) { + timeDelta = m_targetElapsedTicks; + } + + m_leftOverTicks += timeDelta; + + while (m_leftOverTicks >= m_targetElapsedTicks) { + m_elapsedTicks = m_targetElapsedTicks; + m_totalTicks += m_targetElapsedTicks; + m_leftOverTicks -= m_targetElapsedTicks; + m_frameCount++; + + update(); + } + } else { + // Variable timestep update logic. + m_elapsedTicks = timeDelta; + m_totalTicks += timeDelta; + m_leftOverTicks = 0; + m_frameCount++; + + update(); + } + + // Track the current framerate. + if (m_frameCount != lastFrameCount) { + m_framesThisSecond++; + } + + if (m_qpcSecondCounter >= static_cast<uint64_t>(m_qpcFrequency)) { + m_framesPerSecond = m_framesThisSecond; + m_framesThisSecond = 0; + m_qpcSecondCounter %= m_qpcFrequency; + } + } + +private: + // Source timing data uses QPC units. + uint64_t m_qpcFrequency; + uint64_t m_qpcLastTime; + uint64_t m_qpcMaxDelta; + + // Derived timing data uses a canonical tick format. + uint64_t m_elapsedTicks; + uint64_t m_totalTicks; + uint64_t m_leftOverTicks; + + // Members for tracking the framerate. + uint32_t m_frameCount; + uint32_t m_framesPerSecond; + uint32_t m_framesThisSecond; + uint64_t m_qpcSecondCounter; + + // Members for configuring fixed timestep mode. + bool m_isFixedTimeStep; + uint64_t m_targetElapsedTicks; +}; +} // namespace DX diff --git a/support/hololens/ServoApp/Content/GeometryShader.hlsl b/support/hololens/ServoApp/Content/GeometryShader.hlsl new file mode 100644 index 00000000000..b966621d484 --- /dev/null +++ b/support/hololens/ServoApp/Content/GeometryShader.hlsl @@ -0,0 +1,31 @@ +// Per-vertex data from the vertex shader. +struct GeometryShaderInput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + uint instId : TEXCOORD0; +}; + +// Per-vertex data passed to the rasterizer. +struct GeometryShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + uint rtvId : SV_RenderTargetArrayIndex; +}; + +// This geometry shader is a pass-through that leaves the geometry unmodified +// and sets the render target array index. +[maxvertexcount(3)] +void main(triangle GeometryShaderInput input[3], inout TriangleStream<GeometryShaderOutput> outStream) +{ + GeometryShaderOutput output; + [unroll(3)] + for (int i = 0; i < 3; ++i) + { + output.pos = input[i].pos; + output.color = input[i].color; + output.rtvId = input[i].instId; + outStream.Append(output); + } +} diff --git a/support/hololens/ServoApp/Content/PixelShader.hlsl b/support/hololens/ServoApp/Content/PixelShader.hlsl new file mode 100644 index 00000000000..fd857896f51 --- /dev/null +++ b/support/hololens/ServoApp/Content/PixelShader.hlsl @@ -0,0 +1,13 @@ +// Per-pixel color data passed through the pixel shader. +struct PixelShaderInput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; +}; + +// The pixel shader passes through the color data. The color data from +// is interpolated and assigned to a pixel at the rasterization step. +min16float4 main(PixelShaderInput input) : SV_TARGET +{ + return min16float4(input.color, 1.0f); +} diff --git a/support/hololens/ServoApp/Content/ShaderStructures.h b/support/hololens/ServoApp/Content/ShaderStructures.h new file mode 100644 index 00000000000..7de7fa9dae7 --- /dev/null +++ b/support/hololens/ServoApp/Content/ShaderStructures.h @@ -0,0 +1,20 @@ +#pragma once + +namespace Immersive { +// Constant buffer used to send hologram position transform to the shader +// pipeline. +struct ModelConstantBuffer { + DirectX::XMFLOAT4X4 model; +}; + +// Assert that the constant buffer remains 16-byte aligned (best practice). +static_assert((sizeof(ModelConstantBuffer) % (sizeof(float) * 4)) == 0, + "Model constant buffer size must be 16-byte aligned (16 bytes is " + "the length of four floats)."); + +// Used to send per-vertex data to the vertex shader. +struct VertexPositionColor { + DirectX::XMFLOAT3 pos; + DirectX::XMFLOAT3 color; +}; +} // namespace Immersive
\ No newline at end of file diff --git a/support/hololens/ServoApp/Content/SpatialInputHandler.cpp b/support/hololens/ServoApp/Content/SpatialInputHandler.cpp new file mode 100644 index 00000000000..753e8a7efd6 --- /dev/null +++ b/support/hololens/ServoApp/Content/SpatialInputHandler.cpp @@ -0,0 +1,51 @@ +#include "pch.h" +#include "SpatialInputHandler.h" +#include <functional> + +using namespace Immersive; + +using namespace std::placeholders; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::UI::Input::Spatial; + +// Creates and initializes a GestureRecognizer that listens to a Person. +SpatialInputHandler::SpatialInputHandler() { + // The interaction manager provides an event that informs the app when + // spatial interactions are detected. + m_interactionManager = SpatialInteractionManager::GetForCurrentView(); + + // Bind a handler to the SourcePressed event. + m_sourcePressedEventToken = m_interactionManager.SourcePressed( + bind(&SpatialInputHandler::OnSourcePressed, this, _1, _2)); + + // + // TODO: Expand this class to use other gesture-based input events as + // applicable to + // your app. + // +} + +SpatialInputHandler::~SpatialInputHandler() { + // Unregister our handler for the OnSourcePressed event. + m_interactionManager.SourcePressed(m_sourcePressedEventToken); +} + +// Checks if the user performed an input gesture since the last call to this +// method. Allows the main update loop to check for asynchronous changes to the +// user input state. +SpatialInteractionSourceState SpatialInputHandler::CheckForInput() { + SpatialInteractionSourceState sourceState = m_sourceState; + m_sourceState = nullptr; + return sourceState; +} + +void SpatialInputHandler::OnSourcePressed( + SpatialInteractionManager const &, + SpatialInteractionSourceEventArgs const &args) { + m_sourceState = args.State(); + + // + // TODO: In your app or game engine, rewrite this method to queue + // input events in your input class or event handler. + // +} diff --git a/support/hololens/ServoApp/Content/SpatialInputHandler.h b/support/hololens/ServoApp/Content/SpatialInputHandler.h new file mode 100644 index 00000000000..5212cf108ab --- /dev/null +++ b/support/hololens/ServoApp/Content/SpatialInputHandler.h @@ -0,0 +1,34 @@ +#pragma once + +namespace Immersive { +// Sample gesture handler. +// Hooks up events to recognize a tap gesture, and keeps track of input using a +// boolean value. +class SpatialInputHandler { +public: + SpatialInputHandler(); + ~SpatialInputHandler(); + + winrt::Windows::UI::Input::Spatial::SpatialInteractionSourceState + CheckForInput(); + +private: + // Interaction event handler. + void OnSourcePressed( + winrt::Windows::UI::Input::Spatial::SpatialInteractionManager const + &sender, + winrt::Windows::UI::Input::Spatial:: + SpatialInteractionSourceEventArgs const &args); + + // API objects used to process gesture input, and generate gesture events. + winrt::Windows::UI::Input::Spatial::SpatialInteractionManager + m_interactionManager = nullptr; + + // Event registration token. + winrt::event_token m_sourcePressedEventToken; + + // Used to indicate that a Pressed input event was received this frame. + winrt::Windows::UI::Input::Spatial::SpatialInteractionSourceState + m_sourceState = nullptr; +}; +} // namespace Immersive diff --git a/support/hololens/ServoApp/Content/SpinningCubeRenderer.cpp b/support/hololens/ServoApp/Content/SpinningCubeRenderer.cpp new file mode 100644 index 00000000000..c76119bccf7 --- /dev/null +++ b/support/hololens/ServoApp/Content/SpinningCubeRenderer.cpp @@ -0,0 +1,266 @@ +#include "pch.h" +#include "SpinningCubeRenderer.h" +#include "Common/DirectXHelper.h" + +using namespace Immersive; +using namespace DirectX; +using namespace winrt::Windows::Foundation::Numerics; +using namespace winrt::Windows::UI::Input::Spatial; + +// Loads vertex and pixel shaders from files and instantiates the cube geometry. +SpinningCubeRenderer::SpinningCubeRenderer( + std::shared_ptr<DX::DeviceResources> const &deviceResources) + : m_deviceResources(deviceResources) { + CreateDeviceDependentResources(); +} + +// This function uses a SpatialPointerPose to position the world-locked hologram +// two meters in front of the user's heading. +void SpinningCubeRenderer::PositionHologram( + SpatialPointerPose const &pointerPose) { + if (pointerPose != nullptr) { + // Get the gaze direction relative to the given coordinate system. + const float3 headPosition = pointerPose.Head().Position(); + const float3 headDirection = pointerPose.Head().ForwardDirection(); + + // The hologram is positioned two meters along the user's gaze direction. + constexpr float distanceFromUser = 2.0f; // meters + const float3 gazeAtTwoMeters = + headPosition + (distanceFromUser * headDirection); + + // This will be used as the translation component of the hologram's + // model transform. + SetPosition(gazeAtTwoMeters); + } +} + +// Called once per frame. Rotates the cube, and calculates and sets the model +// matrix relative to the position transform indicated by +// hologramPositionTransform. +void SpinningCubeRenderer::Update(DX::StepTimer const &timer) { + // Rotate the cube. + // Convert degrees to radians, then convert seconds to rotation angle. + const float radiansPerSecond = XMConvertToRadians(m_degreesPerSecond); + const double totalRotation = timer.GetTotalSeconds() * radiansPerSecond; + const float radians = static_cast<float>(fmod(totalRotation, XM_2PI)); + const XMMATRIX modelRotation = XMMatrixRotationY(-radians); + + // Position the cube. + const XMMATRIX modelTranslation = + XMMatrixTranslationFromVector(XMLoadFloat3(&m_position)); + + // Multiply to get the transform matrix. + // Note that this transform does not enforce a particular coordinate system. + // The calling class is responsible for rendering this content in a consistent + // manner. + const XMMATRIX modelTransform = + XMMatrixMultiply(modelRotation, modelTranslation); + + // The view and projection matrices are provided by the system; they are + // associated with holographic cameras, and updated on a per-camera basis. + // Here, we provide the model transform for the sample hologram. The model + // transform matrix is transposed to prepare it for the shader. + XMStoreFloat4x4(&m_modelConstantBufferData.model, + XMMatrixTranspose(modelTransform)); + + // Loading is asynchronous. Resources must be created before they can be + // updated. + if (!m_loadingComplete) { + return; + } + + // Use the D3D device context to update Direct3D device-based resources. + const auto context = m_deviceResources->GetD3DDeviceContext(); + + // Update the model transform buffer for the hologram. + context->UpdateSubresource(m_modelConstantBuffer.Get(), 0, nullptr, + &m_modelConstantBufferData, 0, 0); +} + +// Renders one frame using the vertex and pixel shaders. +// On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: +// VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, +// a pass-through geometry shader is also used to set the render +// target array index. +void SpinningCubeRenderer::Render() { + // Loading is asynchronous. Resources must be created before drawing can + // occur. + if (!m_loadingComplete) { + return; + } + + const auto context = m_deviceResources->GetD3DDeviceContext(); + + // Each vertex is one instance of the VertexPositionColor struct. + const UINT stride = sizeof(VertexPositionColor); + const UINT offset = 0; + context->IASetVertexBuffers(0, 1, m_vertexBuffer.GetAddressOf(), &stride, + &offset); + context->IASetIndexBuffer(m_indexBuffer.Get(), + DXGI_FORMAT_R16_UINT, // Each index is one 16-bit + // unsigned integer (short). + 0); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + context->IASetInputLayout(m_inputLayout.Get()); + + // Attach the vertex shader. + context->VSSetShader(m_vertexShader.Get(), nullptr, 0); + // Apply the model constant buffer to the vertex shader. + context->VSSetConstantBuffers(0, 1, m_modelConstantBuffer.GetAddressOf()); + + if (!m_usingVprtShaders) { + // On devices that do not support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature, + // a pass-through geometry shader is used to set the render target + // array index. + context->GSSetShader(m_geometryShader.Get(), nullptr, 0); + } + + // Attach the pixel shader. + context->PSSetShader(m_pixelShader.Get(), nullptr, 0); + + // Draw the objects. + context->DrawIndexedInstanced(m_indexCount, // Index count per instance. + 2, // Instance count. + 0, // Start index location. + 0, // Base vertex location. + 0 // Start instance location. + ); +} + +std::future<void> SpinningCubeRenderer::CreateDeviceDependentResources() { + m_usingVprtShaders = m_deviceResources->GetDeviceSupportsVprt(); + + // On devices that do support the D3D11_FEATURE_D3D11_OPTIONS3:: + // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer optional feature + // we can avoid using a pass-through geometry shader to set the render + // target array index, thus avoiding any overhead that would be + // incurred by setting the geometry shader stage. + std::wstring vertexShaderFileName = m_usingVprtShaders + ? L"ms-appx:///VprtVertexShader.cso" + : L"ms-appx:///VertexShader.cso"; + + // Shaders will be loaded asynchronously. + + // After the vertex shader file is loaded, create the shader and input layout. + std::vector<byte> vertexShaderFileData = + co_await DX::ReadDataAsync(vertexShaderFileName); + winrt::check_hresult(m_deviceResources->GetD3DDevice()->CreateVertexShader( + vertexShaderFileData.data(), vertexShaderFileData.size(), nullptr, + &m_vertexShader)); + + constexpr std::array<D3D11_INPUT_ELEMENT_DESC, 2> vertexDesc = {{ + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, + D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, + D3D11_INPUT_PER_VERTEX_DATA, 0}, + }}; + + winrt::check_hresult(m_deviceResources->GetD3DDevice()->CreateInputLayout( + vertexDesc.data(), static_cast<UINT>(vertexDesc.size()), + vertexShaderFileData.data(), + static_cast<UINT>(vertexShaderFileData.size()), &m_inputLayout)); + + // After the pixel shader file is loaded, create the shader and constant + // buffer. + std::vector<byte> pixelShaderFileData = + co_await DX::ReadDataAsync(L"ms-appx:///PixelShader.cso"); + winrt::check_hresult(m_deviceResources->GetD3DDevice()->CreatePixelShader( + pixelShaderFileData.data(), pixelShaderFileData.size(), nullptr, + &m_pixelShader)); + + const CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelConstantBuffer), + D3D11_BIND_CONSTANT_BUFFER); + winrt::check_hresult(m_deviceResources->GetD3DDevice()->CreateBuffer( + &constantBufferDesc, nullptr, &m_modelConstantBuffer)); + + if (!m_usingVprtShaders) { + // Load the pass-through geometry shader. + std::vector<byte> geometryShaderFileData = + co_await DX::ReadDataAsync(L"ms-appx:///GeometryShader.cso"); + + // After the pass-through geometry shader file is loaded, create the shader. + winrt::check_hresult( + m_deviceResources->GetD3DDevice()->CreateGeometryShader( + geometryShaderFileData.data(), geometryShaderFileData.size(), + nullptr, &m_geometryShader)); + } + + // Load mesh vertices. Each vertex has a position and a color. + // Note that the cube size has changed from the default DirectX app + // template. Windows Holographic is scaled in meters, so to draw the + // cube at a comfortable size we made the cube width 0.2 m (20 cm). + static const std::array<VertexPositionColor, 8> cubeVertices = {{ + {XMFLOAT3(-0.1f, -0.1f, -0.1f), XMFLOAT3(0.0f, 0.0f, 0.0f)}, + {XMFLOAT3(-0.1f, -0.1f, 0.1f), XMFLOAT3(0.0f, 0.0f, 1.0f)}, + {XMFLOAT3(-0.1f, 0.1f, -0.1f), XMFLOAT3(0.0f, 1.0f, 0.0f)}, + {XMFLOAT3(-0.1f, 0.1f, 0.1f), XMFLOAT3(0.0f, 1.0f, 1.0f)}, + {XMFLOAT3(0.1f, -0.1f, -0.1f), XMFLOAT3(1.0f, 0.0f, 0.0f)}, + {XMFLOAT3(0.1f, -0.1f, 0.1f), XMFLOAT3(1.0f, 0.0f, 1.0f)}, + {XMFLOAT3(0.1f, 0.1f, -0.1f), XMFLOAT3(1.0f, 1.0f, 0.0f)}, + {XMFLOAT3(0.1f, 0.1f, 0.1f), XMFLOAT3(1.0f, 1.0f, 1.0f)}, + }}; + + D3D11_SUBRESOURCE_DATA vertexBufferData = {0}; + vertexBufferData.pSysMem = cubeVertices.data(); + vertexBufferData.SysMemPitch = 0; + vertexBufferData.SysMemSlicePitch = 0; + const CD3D11_BUFFER_DESC vertexBufferDesc( + sizeof(VertexPositionColor) * static_cast<UINT>(cubeVertices.size()), + D3D11_BIND_VERTEX_BUFFER); + winrt::check_hresult(m_deviceResources->GetD3DDevice()->CreateBuffer( + &vertexBufferDesc, &vertexBufferData, &m_vertexBuffer)); + + // Load mesh indices. Each trio of indices represents + // a triangle to be rendered on the screen. + // For example: 2,1,0 means that the vertices with indexes + // 2, 1, and 0 from the vertex buffer compose the + // first triangle of this mesh. + // Note that the winding order is clockwise by default. + constexpr std::array<unsigned short, 36> cubeIndices = {{ + 2, 1, 0, // -x + 2, 3, 1, + + 6, 4, 5, // +x + 6, 5, 7, + + 0, 1, 5, // -y + 0, 5, 4, + + 2, 6, 7, // +y + 2, 7, 3, + + 0, 4, 6, // -z + 0, 6, 2, + + 1, 3, 7, // +z + 1, 7, 5, + }}; + + m_indexCount = static_cast<unsigned int>(cubeIndices.size()); + + D3D11_SUBRESOURCE_DATA indexBufferData = {0}; + indexBufferData.pSysMem = cubeIndices.data(); + indexBufferData.SysMemPitch = 0; + indexBufferData.SysMemSlicePitch = 0; + CD3D11_BUFFER_DESC indexBufferDesc(sizeof(unsigned short) * + static_cast<UINT>(cubeIndices.size()), + D3D11_BIND_INDEX_BUFFER); + winrt::check_hresult(m_deviceResources->GetD3DDevice()->CreateBuffer( + &indexBufferDesc, &indexBufferData, &m_indexBuffer)); + + // Once the cube is loaded, the object is ready to be rendered. + m_loadingComplete = true; +}; + +void SpinningCubeRenderer::ReleaseDeviceDependentResources() { + m_loadingComplete = false; + m_usingVprtShaders = false; + m_vertexShader.Reset(); + m_inputLayout.Reset(); + m_pixelShader.Reset(); + m_geometryShader.Reset(); + m_modelConstantBuffer.Reset(); + m_vertexBuffer.Reset(); + m_indexBuffer.Reset(); +} diff --git a/support/hololens/ServoApp/Content/SpinningCubeRenderer.h b/support/hololens/ServoApp/Content/SpinningCubeRenderer.h new file mode 100644 index 00000000000..50f69609d88 --- /dev/null +++ b/support/hololens/ServoApp/Content/SpinningCubeRenderer.h @@ -0,0 +1,57 @@ +#pragma once + +#include "../Common/DeviceResources.h" +#include "../Common/StepTimer.h" +#include "ShaderStructures.h" + +namespace Immersive { +// This sample renderer instantiates a basic rendering pipeline. +class SpinningCubeRenderer { +public: + SpinningCubeRenderer( + std::shared_ptr<DX::DeviceResources> const &deviceResources); + std::future<void> CreateDeviceDependentResources(); + void ReleaseDeviceDependentResources(); + void Update(DX::StepTimer const &timer); + void Render(); + + // Repositions the sample hologram. + void + PositionHologram(winrt::Windows::UI::Input::Spatial::SpatialPointerPose const + &pointerPose); + + // Property accessors. + void SetPosition(winrt::Windows::Foundation::Numerics::float3 const &pos) { + m_position = pos; + } + winrt::Windows::Foundation::Numerics::float3 const &GetPosition() { + return m_position; + } + +private: + // Cached pointer to device resources. + std::shared_ptr<DX::DeviceResources> m_deviceResources; + + // Direct3D resources for cube geometry. + Microsoft::WRL::ComPtr<ID3D11InputLayout> m_inputLayout; + Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer; + Microsoft::WRL::ComPtr<ID3D11Buffer> m_indexBuffer; + Microsoft::WRL::ComPtr<ID3D11VertexShader> m_vertexShader; + Microsoft::WRL::ComPtr<ID3D11GeometryShader> m_geometryShader; + Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pixelShader; + Microsoft::WRL::ComPtr<ID3D11Buffer> m_modelConstantBuffer; + + // System resources for cube geometry. + ModelConstantBuffer m_modelConstantBufferData; + uint32_t m_indexCount = 0; + + // Variables used with the rendering loop. + bool m_loadingComplete = false; + float m_degreesPerSecond = 45.f; + winrt::Windows::Foundation::Numerics::float3 m_position = {0.f, 0.f, -2.f}; + + // If the current D3D Device supports VPRT, we can avoid using a geometry + // shader just to set the render target array index. + bool m_usingVprtShaders = false; +}; +} // namespace Immersive diff --git a/support/hololens/ServoApp/Content/VPRTVertexShader.hlsl b/support/hololens/ServoApp/Content/VPRTVertexShader.hlsl new file mode 100644 index 00000000000..8b6dd6c7428 --- /dev/null +++ b/support/hololens/ServoApp/Content/VPRTVertexShader.hlsl @@ -0,0 +1,11 @@ +// Per-vertex data passed to the geometry shader. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + + // The render target array index is set here in the vertex shader. + uint viewId : SV_RenderTargetArrayIndex; +}; + +#include "VertexShaderShared.hlsl" diff --git a/support/hololens/ServoApp/Content/VertexShader.hlsl b/support/hololens/ServoApp/Content/VertexShader.hlsl new file mode 100644 index 00000000000..f8ae0e14920 --- /dev/null +++ b/support/hololens/ServoApp/Content/VertexShader.hlsl @@ -0,0 +1,11 @@ +// Per-vertex data passed to the geometry shader. +struct VertexShaderOutput +{ + min16float4 pos : SV_POSITION; + min16float3 color : COLOR0; + + // The render target array index will be set by the geometry shader. + uint viewId : TEXCOORD0; +}; + +#include "VertexShaderShared.hlsl" diff --git a/support/hololens/ServoApp/Content/VertexShaderShared.hlsl b/support/hololens/ServoApp/Content/VertexShaderShared.hlsl new file mode 100644 index 00000000000..7a49de6fab4 --- /dev/null +++ b/support/hololens/ServoApp/Content/VertexShaderShared.hlsl @@ -0,0 +1,47 @@ +// A constant buffer that stores the model transform. +cbuffer ModelConstantBuffer : register(b0) +{ + float4x4 model; +}; + +// A constant buffer that stores each set of view and projection matrices in column-major format. +cbuffer ViewProjectionConstantBuffer : register(b1) +{ + float4x4 viewProjection[2]; +}; + +// Per-vertex data used as input to the vertex shader. +struct VertexShaderInput +{ + min16float3 pos : POSITION; + min16float3 color : COLOR0; + uint instId : SV_InstanceID; +}; + +// Simple shader to do vertex processing on the GPU. +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Note which view this vertex has been sent to. Used for matrix lookup. + // Taking the modulo of the instance ID allows geometry instancing to be used + // along with stereo instanced drawing; in that case, two copies of each + // instance would be drawn, one for left and one for right. + int idx = input.instId % 2; + + // Transform the vertex position into world space. + pos = mul(pos, model); + + // Correct for perspective and project the vertex position onto the screen. + pos = mul(pos, viewProjection[idx]); + output.pos = (min16float4)pos; + + // Pass the color through without modification. + output.color = input.color; + + // Set the render target array index. + output.viewId = idx; + + return output; +} diff --git a/support/hololens/ServoApp/ImmersiveMain.cpp b/support/hololens/ServoApp/ImmersiveMain.cpp new file mode 100644 index 00000000000..26b8ea56406 --- /dev/null +++ b/support/hololens/ServoApp/ImmersiveMain.cpp @@ -0,0 +1,557 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "pch.h" +#include "ImmersiveMain.h" +#include "Common/DirectXHelper.h" + +#include <windows.graphics.directx.direct3d11.interop.h> + +using namespace Immersive; +using namespace concurrency; +using namespace Microsoft::WRL; +using namespace std::placeholders; +using namespace winrt::Windows::Foundation::Numerics; +using namespace winrt::Windows::Gaming::Input; +using namespace winrt::Windows::Graphics::Holographic; +using namespace winrt::Windows::Graphics::DirectX::Direct3D11; +using namespace winrt::Windows::Perception::Spatial; +using namespace winrt::Windows::UI::Input::Spatial; + +// Loads and initializes application assets when the application is loaded. +ImmersiveMain::ImmersiveMain( + std::shared_ptr<DX::DeviceResources> const &deviceResources) + : m_deviceResources(deviceResources) { + // Register to be notified if the device is lost or recreated. + m_deviceResources->RegisterDeviceNotify(this); + + // If connected, a game controller can also be used for input. + m_gamepadAddedEventToken = + Gamepad::GamepadAdded(bind(&ImmersiveMain::OnGamepadAdded, this, _1, _2)); + m_gamepadRemovedEventToken = Gamepad::GamepadRemoved( + bind(&ImmersiveMain::OnGamepadRemoved, this, _1, _2)); + + for (Gamepad const &gamepad : Gamepad::Gamepads()) { + OnGamepadAdded(nullptr, gamepad); + } + + m_canGetHolographicDisplayForCamera = + winrt::Windows::Foundation::Metadata::ApiInformation::IsPropertyPresent( + L"Windows.Graphics.Holographic.HolographicCamera", L"Display"); + m_canGetDefaultHolographicDisplay = + winrt::Windows::Foundation::Metadata::ApiInformation::IsMethodPresent( + L"Windows.Graphics.Holographic.HolographicDisplay", L"GetDefault"); + m_canCommitDirect3D11DepthBuffer = + winrt::Windows::Foundation::Metadata::ApiInformation::IsMethodPresent( + L"Windows.Graphics.Holographic.HolographicCameraRenderingParameters", + L"CommitDirect3D11DepthBuffer"); + + if (m_canGetDefaultHolographicDisplay) { + // Subscribe for notifications about changes to the state of the default + // HolographicDisplay and its SpatialLocator. + m_holographicDisplayIsAvailableChangedEventToken = + HolographicSpace::IsAvailableChanged( + bind(&ImmersiveMain::OnHolographicDisplayIsAvailableChanged, this, + _1, _2)); + } + + // Acquire the current state of the default HolographicDisplay and its + // SpatialLocator. + OnHolographicDisplayIsAvailableChanged(nullptr, nullptr); +} + +void ImmersiveMain::SetHolographicSpace( + HolographicSpace const &holographicSpace) { + UnregisterHolographicEventHandlers(); + + m_holographicSpace = holographicSpace; + + // + // TODO: Add code here to initialize your holographic content. + // + +#ifdef DRAW_SAMPLE_CONTENT + // Initialize the sample hologram. + m_spinningCubeRenderer = + std::make_unique<SpinningCubeRenderer>(m_deviceResources); + m_spatialInputHandler = std::make_unique<SpatialInputHandler>(); +#endif + + // Respond to camera added events by creating any resources that are specific + // to that camera, such as the back buffer render target view. + // When we add an event handler for CameraAdded, the API layer will avoid + // putting the new camera in new HolographicFrames until we complete the + // deferral we created for that handler, or return from the handler without + // creating a deferral. This allows the app to take more than one frame to + // finish creating resources and loading assets for the new holographic + // camera. This function should be registered before the app creates any + // HolographicFrames. + m_cameraAddedToken = m_holographicSpace.CameraAdded( + std::bind(&ImmersiveMain::OnCameraAdded, this, _1, _2)); + + // Respond to camera removed events by releasing resources that were created + // for that camera. When the app receives a CameraRemoved event, it releases + // all references to the back buffer right away. This includes render target + // views, Direct2D target bitmaps, and so on. The app must also ensure that + // the back buffer is not attached as a render target, as shown in + // DeviceResources::ReleaseResourcesForBackBuffer. + m_cameraRemovedToken = m_holographicSpace.CameraRemoved( + std::bind(&ImmersiveMain::OnCameraRemoved, this, _1, _2)); + + // Notes on spatial tracking APIs: + // * Stationary reference frames are designed to provide a best-fit position + // relative to the + // overall space. Individual positions within that reference frame are + // allowed to drift slightly as the device learns more about the + // environment. + // * When precise placement of individual holograms is required, a + // SpatialAnchor should be used to + // anchor the individual hologram to a position in the real world - for + // example, a point the user indicates to be of special interest. Anchor + // positions do not drift, but can be corrected; the anchor will use the + // corrected position starting in the next frame after the correction has + // occurred. +} + +void ImmersiveMain::UnregisterHolographicEventHandlers() { + if (m_holographicSpace != nullptr) { + // Clear previous event registrations. + m_holographicSpace.CameraAdded(m_cameraAddedToken); + m_cameraAddedToken = {}; + m_holographicSpace.CameraRemoved(m_cameraRemovedToken); + m_cameraRemovedToken = {}; + } + + if (m_spatialLocator != nullptr) { + m_spatialLocator.LocatabilityChanged(m_locatabilityChangedToken); + } +} + +ImmersiveMain::~ImmersiveMain() { + // Deregister device notification. + m_deviceResources->RegisterDeviceNotify(nullptr); + + UnregisterHolographicEventHandlers(); + + Gamepad::GamepadAdded(m_gamepadAddedEventToken); + Gamepad::GamepadRemoved(m_gamepadRemovedEventToken); + HolographicSpace::IsAvailableChanged( + m_holographicDisplayIsAvailableChangedEventToken); +} + +// Updates the application state once per frame. +HolographicFrame ImmersiveMain::Update() { + // Before doing the timer update, there is some work to do per-frame + // to maintain holographic rendering. First, we will get information + // about the current frame. + + // The HolographicFrame has information that the app needs in order + // to update and render the current frame. The app begins each new + // frame by calling CreateNextFrame. + HolographicFrame holographicFrame = m_holographicSpace.CreateNextFrame(); + + // Get a prediction of where holographic cameras will be when this frame + // is presented. + HolographicFramePrediction prediction = holographicFrame.CurrentPrediction(); + + // Back buffers can change from frame to frame. Validate each buffer, and + // recreate resource views and depth buffers as needed. + m_deviceResources->EnsureCameraResources(holographicFrame, prediction); + +#ifdef DRAW_SAMPLE_CONTENT + if (m_stationaryReferenceFrame != nullptr) { + // Check for new input state since the last frame. + for (GamepadWithButtonState &gamepadWithButtonState : m_gamepads) { + bool buttonDownThisUpdate = + ((gamepadWithButtonState.gamepad.GetCurrentReading().Buttons & + GamepadButtons::A) == GamepadButtons::A); + if (buttonDownThisUpdate && + !gamepadWithButtonState.buttonAWasPressedLastFrame) { + m_pointerPressed = true; + } + gamepadWithButtonState.buttonAWasPressedLastFrame = buttonDownThisUpdate; + } + + SpatialInteractionSourceState pointerState = + m_spatialInputHandler->CheckForInput(); + SpatialPointerPose pose = nullptr; + if (pointerState != nullptr) { + pose = pointerState.TryGetPointerPose( + m_stationaryReferenceFrame.CoordinateSystem()); + } else if (m_pointerPressed) { + pose = SpatialPointerPose::TryGetAtTimestamp( + m_stationaryReferenceFrame.CoordinateSystem(), + prediction.Timestamp()); + } + m_pointerPressed = false; + + // When a Pressed gesture is detected, the sample hologram will be + // repositioned two meters in front of the user. + m_spinningCubeRenderer->PositionHologram(pose); + } +#endif + + m_timer.Tick([this]() { + // + // TODO: Update scene objects. + // + // Put time-based updates here. By default this code will run once per frame, + // but if you change the StepTimer to use a fixed time step this code will + // run as many times as needed to get to the current step. + // + +#ifdef DRAW_SAMPLE_CONTENT + m_spinningCubeRenderer->Update(m_timer); +#endif + }); + + if (!m_canCommitDirect3D11DepthBuffer) { + // On versions of the platform that do not support the + // CommitDirect3D11DepthBuffer API, we can control image stabilization by + // setting a focus point with optional plane normal and velocity. + for (HolographicCameraPose const &cameraPose : prediction.CameraPoses()) { +#ifdef DRAW_SAMPLE_CONTENT + // The HolographicCameraRenderingParameters class provides access to set + // the image stabilization parameters. + HolographicCameraRenderingParameters renderingParameters = + holographicFrame.GetRenderingParameters(cameraPose); + + // SetFocusPoint informs the system about a specific point in your scene + // to prioritize for image stabilization. The focus point is set + // independently for each holographic camera. When setting the focus + // point, put it on or near content that the user is looking at. In this + // example, we put the focus point at the center of the sample hologram. + // You can also set the relative velocity and facing of the stabilization + // plane using overloads of this method. + if (m_stationaryReferenceFrame != nullptr) { + renderingParameters.SetFocusPoint( + m_stationaryReferenceFrame.CoordinateSystem(), + m_spinningCubeRenderer->GetPosition()); + } +#endif + } + } + + // The holographic frame will be used to get up-to-date view and projection + // matrices and to present the swap chain. + return holographicFrame; +} + +// Renders the current frame to each holographic camera, according to the +// current application and spatial positioning state. Returns true if the +// frame was rendered to at least one camera. +bool ImmersiveMain::Render(HolographicFrame const &holographicFrame) { + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) { + return false; + } + + // + // TODO: Add code for pre-pass rendering here. + // + // Take care of any tasks that are not specific to an individual holographic + // camera. This includes anything that doesn't need the final view or + // projection matrix, such as lighting maps. + // + + // Lock the set of holographic camera resources, then draw to each camera + // in this frame. + return m_deviceResources->UseHolographicCameraResources<bool>( + [this, + holographicFrame](std::map<UINT32, std::unique_ptr<DX::CameraResources>> + &cameraResourceMap) { + // Up-to-date frame predictions enhance the effectiveness of image + // stablization and allow more accurate positioning of holograms. + holographicFrame.UpdateCurrentPrediction(); + HolographicFramePrediction prediction = + holographicFrame.CurrentPrediction(); + + bool atLeastOneCameraRendered = false; + for (HolographicCameraPose const &cameraPose : + prediction.CameraPoses()) { + // This represents the device-based resources for a HolographicCamera. + DX::CameraResources *pCameraResources = + cameraResourceMap[cameraPose.HolographicCamera().Id()].get(); + + // Get the device context. + const auto context = m_deviceResources->GetD3DDeviceContext(); + const auto depthStencilView = pCameraResources->GetDepthStencilView(); + + // Set render targets to the current holographic camera. + ID3D11RenderTargetView *const targets[1] = { + pCameraResources->GetBackBufferRenderTargetView()}; + context->OMSetRenderTargets(1, targets, depthStencilView); + + // Clear the back buffer and depth stencil view. + if (m_canGetHolographicDisplayForCamera && + cameraPose.HolographicCamera().Display().IsOpaque()) { + context->ClearRenderTargetView(targets[0], + DirectX::Colors::CornflowerBlue); + } else { + context->ClearRenderTargetView(targets[0], + DirectX::Colors::Transparent); + } + context->ClearDepthStencilView( + depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, + 0); + + // + // TODO: Replace the sample content with your own content. + // + // Notes regarding holographic content: + // * For drawing, remember that you have the potential to fill + // twice as many pixels + // in a stereoscopic render target as compared to a + // non-stereoscopic render target of the same resolution. Avoid + // unnecessary or repeated writes to the same pixel, and only + // draw holograms that the user can see. + // * To help occlude hologram geometry, you can create a depth map + // using geometry + // data obtained via the surface mapping APIs. You can use this + // depth map to avoid rendering holograms that are intended to be + // hidden behind tables, walls, monitors, and so on. + // * On HolographicDisplays that are transparent, black pixels will + // appear transparent + // to the user. On such devices, you should clear the screen to + // Transparent as shown above. You should still use alpha + // blending to draw semitransparent holograms. + // + + // The view and projection matrices for each holographic camera will + // change every frame. This function refreshes the data in the + // constant buffer for the holographic camera indicated by cameraPose. + if (m_stationaryReferenceFrame) { + pCameraResources->UpdateViewProjectionBuffer( + m_deviceResources, cameraPose, + m_stationaryReferenceFrame.CoordinateSystem()); + } + + // Attach the view/projection constant buffer for this camera to the + // graphics pipeline. + bool cameraActive = + pCameraResources->AttachViewProjectionBuffer(m_deviceResources); + +#ifdef DRAW_SAMPLE_CONTENT + // Only render world-locked content when positional tracking is + // active. + if (cameraActive) { + // Draw the sample hologram. + m_spinningCubeRenderer->Render(); + if (m_canCommitDirect3D11DepthBuffer) { + // On versions of the platform that support the + // CommitDirect3D11DepthBuffer API, we can provide the depth + // buffer to the system, and it will use depth information to + // stabilize the image at a per-pixel level. + HolographicCameraRenderingParameters renderingParameters = + holographicFrame.GetRenderingParameters(cameraPose); + + IDirect3DSurface interopSurface = + DX::CreateDepthTextureInteropObject( + pCameraResources->GetDepthStencilTexture2D()); + + // Calling CommitDirect3D11DepthBuffer causes the system to queue + // Direct3D commands to read the depth buffer. It will then use + // that information to stabilize the image as the HolographicFrame + // is presented. + renderingParameters.CommitDirect3D11DepthBuffer(interopSurface); + } + } +#endif + atLeastOneCameraRendered = true; + } + + return atLeastOneCameraRendered; + }); +} + +void ImmersiveMain::SaveAppState() { + // + // TODO: Insert code here to save your app state. + // This method is called when the app is about to suspend. + // + // For example, store information in the SpatialAnchorStore. + // +} + +void ImmersiveMain::LoadAppState() { + // + // TODO: Insert code here to load your app state. + // This method is called when the app resumes. + // + // For example, load information from the SpatialAnchorStore. + // +} + +void ImmersiveMain::OnPointerPressed() { m_pointerPressed = true; } + +// Notifies classes that use Direct3D device resources that the device resources +// need to be released before this method returns. +void ImmersiveMain::OnDeviceLost() { +#ifdef DRAW_SAMPLE_CONTENT + m_spinningCubeRenderer->ReleaseDeviceDependentResources(); +#endif +} + +// Notifies classes that use Direct3D device resources that the device resources +// may now be recreated. +void ImmersiveMain::OnDeviceRestored() { +#ifdef DRAW_SAMPLE_CONTENT + m_spinningCubeRenderer->CreateDeviceDependentResources(); +#endif +} + +void ImmersiveMain::OnLocatabilityChanged( + SpatialLocator const &sender, + winrt::Windows::Foundation::IInspectable const &) { + switch (sender.Locatability()) { + case SpatialLocatability::Unavailable: + // Holograms cannot be rendered. + { + winrt::hstring message(L"Warning! Positional tracking is " + + std::to_wstring(int(sender.Locatability())) + + L".\n"); + OutputDebugStringW(message.data()); + } + break; + + // In the following three cases, it is still possible to place holograms using + // a SpatialLocatorAttachedFrameOfReference. + case SpatialLocatability::PositionalTrackingActivating: + // The system is preparing to use positional tracking. + + case SpatialLocatability::OrientationOnly: + // Positional tracking has not been activated. + + case SpatialLocatability::PositionalTrackingInhibited: + // Positional tracking is temporarily inhibited. User action may be required + // in order to restore positional tracking. + break; + + case SpatialLocatability::PositionalTrackingActive: + // Positional tracking is active. World-locked content can be rendered. + break; + } +} + +void ImmersiveMain::OnCameraAdded( + HolographicSpace const &, + HolographicSpaceCameraAddedEventArgs const &args) { + winrt::Windows::Foundation::Deferral deferral = args.GetDeferral(); + HolographicCamera holographicCamera = args.Camera(); + create_task([this, deferral, holographicCamera]() { + // + // TODO: Allocate resources for the new camera and load any content specific + // to + // that camera. Note that the render target size (in pixels) is a + // property of the HolographicCamera object, and can be used to create + // off-screen render targets that match the resolution of the + // HolographicCamera. + // + + // Create device-based resources for the holographic camera and add it to + // the list of cameras used for updates and rendering. Notes: + // * Since this function may be called at any time, the + // AddHolographicCamera function + // waits until it can get a lock on the set of holographic camera + // resources before adding the new camera. At 60 frames per second this + // wait should not take long. + // * A subsequent Update will take the back buffer from the + // RenderingParameters of this + // camera's CameraPose and use it to create the ID3D11RenderTargetView + // for this camera. Content can then be rendered for the + // HolographicCamera. + m_deviceResources->AddHolographicCamera(holographicCamera); + + // Holographic frame predictions will not include any information about this + // camera until the deferral is completed. + deferral.Complete(); + }); +} + +void ImmersiveMain::OnCameraRemoved( + HolographicSpace const &, + HolographicSpaceCameraRemovedEventArgs const &args) { + create_task([this]() { + // + // TODO: Asynchronously unload or deactivate content resources (not back + // buffer + // resources) that are specific only to the camera that was removed. + // + }); + + // Before letting this callback return, ensure that all references to the back + // buffer are released. Since this function may be called at any time, the + // RemoveHolographicCamera function waits until it can get a lock on the set + // of holographic camera resources before deallocating resources for this + // camera. At 60 frames per second this wait should not take long. + m_deviceResources->RemoveHolographicCamera(args.Camera()); +} + +void ImmersiveMain::OnGamepadAdded(winrt::Windows::Foundation::IInspectable, + Gamepad const &args) { + for (GamepadWithButtonState const &gamepadWithButtonState : m_gamepads) { + if (args == gamepadWithButtonState.gamepad) { + // This gamepad is already in the list. + return; + } + } + + GamepadWithButtonState newGamepad = {args, false}; + m_gamepads.push_back(newGamepad); +} + +void ImmersiveMain::OnGamepadRemoved(winrt::Windows::Foundation::IInspectable, + Gamepad const &args) { + m_gamepads.erase( + std::remove_if(m_gamepads.begin(), m_gamepads.end(), + [&](GamepadWithButtonState &gamepadWithState) { + return gamepadWithState.gamepad == args; + }), + m_gamepads.end()); +} + +void ImmersiveMain::OnHolographicDisplayIsAvailableChanged( + winrt::Windows::Foundation::IInspectable, + winrt::Windows::Foundation::IInspectable) { + // Get the spatial locator for the default HolographicDisplay, if one is + // available. + SpatialLocator spatialLocator = nullptr; + if (m_canGetDefaultHolographicDisplay) { + HolographicDisplay defaultHolographicDisplay = + HolographicDisplay::GetDefault(); + if (defaultHolographicDisplay) { + spatialLocator = defaultHolographicDisplay.SpatialLocator(); + } + } else { + spatialLocator = SpatialLocator::GetDefault(); + } + + if (m_spatialLocator != spatialLocator) { + // If the spatial locator is disconnected or replaced, we should discard all + // state that was based on it. + if (m_spatialLocator != nullptr) { + m_spatialLocator.LocatabilityChanged(m_locatabilityChangedToken); + m_spatialLocator = nullptr; + } + + m_stationaryReferenceFrame = nullptr; + + if (spatialLocator != nullptr) { + // Use the SpatialLocator from the default HolographicDisplay to track the + // motion of the device. + m_spatialLocator = spatialLocator; + + // Respond to changes in the positional tracking state. + m_locatabilityChangedToken = m_spatialLocator.LocatabilityChanged( + std::bind(&ImmersiveMain::OnLocatabilityChanged, this, _1, _2)); + + // The simplest way to render world-locked holograms is to create a + // stationary reference frame based on a SpatialLocator. This is roughly + // analogous to creating a "world" coordinate system with the origin + // placed at the device's position as the app is launched. + m_stationaryReferenceFrame = + m_spatialLocator.CreateStationaryFrameOfReferenceAtCurrentLocation(); + } + } +} diff --git a/support/hololens/ServoApp/ImmersiveMain.h b/support/hololens/ServoApp/ImmersiveMain.h new file mode 100644 index 00000000000..404b18c9e10 --- /dev/null +++ b/support/hololens/ServoApp/ImmersiveMain.h @@ -0,0 +1,151 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once + +// +// Comment out this preprocessor definition to disable all of the +// sample content. +// +// To remove the content after disabling it: +// * Remove the unused code from your app's Main class. +// * Delete the Content folder provided with this template. +// +#define DRAW_SAMPLE_CONTENT + +#include "Common/DeviceResources.h" +#include "Common/StepTimer.h" + +#ifdef DRAW_SAMPLE_CONTENT +#include "Content/SpinningCubeRenderer.h" +#include "Content/SpatialInputHandler.h" +#endif + +// Updates, renders, and presents holographic content using Direct3D. +namespace Immersive { +class ImmersiveMain : public DX::IDeviceNotify { +public: + ImmersiveMain(std::shared_ptr<DX::DeviceResources> const &deviceResources); + ~ImmersiveMain(); + + // Sets the holographic space. This is our closest analogue to setting a new + // window for the app. + void SetHolographicSpace( + winrt::Windows::Graphics::Holographic::HolographicSpace const + &holographicSpace); + + // Starts the holographic frame and updates the content. + winrt::Windows::Graphics::Holographic::HolographicFrame Update(); + + // Renders holograms, including world-locked content. + bool Render(winrt::Windows::Graphics::Holographic::HolographicFrame const + &holographicFrame); + + // Handle saving and loading of app state owned by AppMain. + void SaveAppState(); + void LoadAppState(); + + // Handle mouse input. + void OnPointerPressed(); + + // IDeviceNotify + void OnDeviceLost() override; + void OnDeviceRestored() override; + +private: + // Asynchronously creates resources for new holographic cameras. + void OnCameraAdded( + winrt::Windows::Graphics::Holographic::HolographicSpace const &sender, + winrt::Windows::Graphics::Holographic:: + HolographicSpaceCameraAddedEventArgs const &args); + + // Synchronously releases resources for holographic cameras that are no longer + // attached to the system. + void OnCameraRemoved( + winrt::Windows::Graphics::Holographic::HolographicSpace const &sender, + winrt::Windows::Graphics::Holographic:: + HolographicSpaceCameraRemovedEventArgs const &args); + + // Used to notify the app when the positional tracking state changes. + void OnLocatabilityChanged( + winrt::Windows::Perception::Spatial::SpatialLocator const &sender, + winrt::Windows::Foundation::IInspectable const &args); + + // Used to be aware of gamepads that are plugged in after the app starts. + void OnGamepadAdded(winrt::Windows::Foundation::IInspectable, + winrt::Windows::Gaming::Input::Gamepad const &args); + + // Used to stop looking for gamepads that are removed while the app is + // running. + void OnGamepadRemoved(winrt::Windows::Foundation::IInspectable, + winrt::Windows::Gaming::Input::Gamepad const &args); + + // Used to respond to changes to the default spatial locator. + void OnHolographicDisplayIsAvailableChanged( + winrt::Windows::Foundation::IInspectable, + winrt::Windows::Foundation::IInspectable); + + // Clears event registration state. Used when changing to a new + // HolographicSpace and when tearing down AppMain. + void UnregisterHolographicEventHandlers(); + +#ifdef DRAW_SAMPLE_CONTENT + // Renders a colorful holographic cube that's 20 centimeters wide. This sample + // content is used to demonstrate world-locked rendering. + std::unique_ptr<SpinningCubeRenderer> m_spinningCubeRenderer; + + // Listens for the Pressed spatial input event. + std::shared_ptr<SpatialInputHandler> m_spatialInputHandler; +#endif + + // Cached pointer to device resources. + std::shared_ptr<DX::DeviceResources> m_deviceResources; + + // Render loop timer. + DX::StepTimer m_timer; + + // Represents the holographic space around the user. + winrt::Windows::Graphics::Holographic::HolographicSpace m_holographicSpace = + nullptr; + + // SpatialLocator that is attached to the default HolographicDisplay. + winrt::Windows::Perception::Spatial::SpatialLocator m_spatialLocator = + nullptr; + + // A stationary reference frame based on m_spatialLocator. + winrt::Windows::Perception::Spatial::SpatialStationaryFrameOfReference + m_stationaryReferenceFrame = nullptr; + + // Event registration tokens. + winrt::event_token m_cameraAddedToken; + winrt::event_token m_cameraRemovedToken; + winrt::event_token m_locatabilityChangedToken; + winrt::event_token m_gamepadAddedEventToken; + winrt::event_token m_gamepadRemovedEventToken; + winrt::event_token m_holographicDisplayIsAvailableChangedEventToken; + + // Keep track of gamepads. + struct GamepadWithButtonState { + winrt::Windows::Gaming::Input::Gamepad gamepad; + bool buttonAWasPressedLastFrame = false; + }; + std::vector<GamepadWithButtonState> m_gamepads; + + // Keep track of mouse input. + bool m_pointerPressed = false; + + // Cache whether or not the HolographicCamera.Display property can be + // accessed. + bool m_canGetHolographicDisplayForCamera = false; + + // Cache whether or not the HolographicDisplay.GetDefault() method can be + // called. + bool m_canGetDefaultHolographicDisplay = false; + + // Cache whether or not the + // HolographicCameraRenderingParameters.CommitDirect3D11DepthBuffer() method + // can be called. + bool m_canCommitDirect3D11DepthBuffer = false; +}; +} // namespace Immersive diff --git a/support/hololens/ServoApp/ImmersiveView.cpp b/support/hololens/ServoApp/ImmersiveView.cpp new file mode 100644 index 00000000000..9babc272299 --- /dev/null +++ b/support/hololens/ServoApp/ImmersiveView.cpp @@ -0,0 +1,236 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "pch.h" +#include "logs.h" +#include "ImmersiveView.h" +#include "ImmersiveMain.h" + +using namespace winrt::ServoApp; + +using namespace concurrency; +using namespace std::placeholders; +using namespace winrt::Windows::ApplicationModel; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::ApplicationModel::Core; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Graphics::Holographic; +using namespace winrt::Windows::UI::Core; + +// Immediatly start immersive mode: +// int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) +//{ +// winrt::init_apartment(); +// CoreApplication::Run(ImmersiveViewSource()); +// return 0; +//} + +// IFrameworkViewSource methods + +IFrameworkView ImmersiveViewSource::CreateView() { return holographicView; } + +// IFrameworkView methods + +// The first method called when the IFrameworkView is being created. +// Use this method to subscribe for Windows shell events and to initialize your +// app. +void ImmersiveView::Initialize(CoreApplicationView const &applicationView) { + applicationView.Activated( + std::bind(&ImmersiveView::OnViewActivated, this, _1, _2)); + + // Register event handlers for app lifecycle. + m_suspendingEventToken = CoreApplication::Suspending( + bind(&ImmersiveView::OnSuspending, this, _1, _2)); + m_resumingEventToken = + CoreApplication::Resuming(bind(&ImmersiveView::OnResuming, this, _1, _2)); + + // At this point we have access to the device and we can create + // device-dependent resources. + m_deviceResources = std::make_shared<DX::DeviceResources>(); + + m_main = std::make_unique<Immersive::ImmersiveMain>(m_deviceResources); +} + +// Called when the CoreWindow object is created (or re-created). +void ImmersiveView::SetWindow(CoreWindow const &window) { + + if (m_main == nullptr) { + winrt::hstring message(L"main program not intialized.\n"); + OutputDebugStringW(message.data()); + return; + } + + // Register for keypress notifications. + m_keyDownEventToken = + window.KeyDown(bind(&ImmersiveView::OnKeyPressed, this, _1, _2)); + + // Register for pointer pressed notifications. + m_pointerPressedEventToken = window.PointerPressed( + bind(&ImmersiveView::OnPointerPressed, this, _1, _2)); + + // Register for notification that the app window is being closed. + m_windowClosedEventToken = + window.Closed(bind(&ImmersiveView::OnWindowClosed, this, _1, _2)); + + // Register for notifications that the app window is losing focus. + m_visibilityChangedEventToken = window.VisibilityChanged( + bind(&ImmersiveView::OnVisibilityChanged, this, _1, _2)); + + // Create a holographic space for the core window for the current view. + // Presenting holographic frames that are created by this holographic space + // will put the app into exclusive mode. + m_holographicSpace = HolographicSpace::CreateForCoreWindow(window); + + // The DeviceResources class uses the preferred DXGI adapter ID from the + // holographic space (when available) to create a Direct3D device. The + // HolographicSpace uses this ID3D11Device to create and manage device-based + // resources such as swap chains. + m_deviceResources->SetHolographicSpace(m_holographicSpace); + + // The main class uses the holographic space for updates and rendering. + m_main->SetHolographicSpace(m_holographicSpace); +} + +// The Load method can be used to initialize scene resources or to load a +// previously saved app state. +void ImmersiveView::Load(winrt::hstring const &) {} + +// This method is called after the window becomes active. It oversees the +// update, draw, and present loop, and it also oversees window message +// processing. +void ImmersiveView::Run() { + + if (m_main == nullptr) { + winrt::hstring message(L"main program not intialized.\n"); + OutputDebugStringW(message.data()); + return; + } + + CoreWindow::GetForCurrentThread().Activate(); + + while (!m_windowClosed) { + if (m_windowVisible && (m_holographicSpace != nullptr)) { + CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents( + CoreProcessEventsOption::ProcessAllIfPresent); + + HolographicFrame holographicFrame = m_main->Update(); + + if (m_main->Render(holographicFrame)) { + // The holographic frame has an API that presents the swap chain for + // each holographic camera. + m_deviceResources->Present(holographicFrame); + } + } else { + CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents( + CoreProcessEventsOption::ProcessOneAndAllPending); + } + } +} + +// Terminate events do not cause Uninitialize to be called. It will be called if +// your IFrameworkView class is torn down while the app is in the foreground, +// for example if the Run method exits. +void ImmersiveView::Uninitialize() { + m_main.reset(); + m_deviceResources.reset(); + + CoreApplication::Suspending(m_suspendingEventToken); + CoreApplication::Resuming(m_resumingEventToken); + + auto const &window = CoreWindow::GetForCurrentThread(); + window.KeyDown(m_keyDownEventToken); + window.PointerPressed(m_pointerPressedEventToken); + window.Closed(m_windowClosedEventToken); + window.VisibilityChanged(m_visibilityChangedEventToken); +} + +// Application lifecycle event handlers + +// Called when the app is prelaunched. Use this method to load resources ahead +// of time and enable faster launch times. +void ImmersiveView::OnLaunched(LaunchActivatedEventArgs const &args) { + if (args.PrelaunchActivated()) { + // + // TODO: Insert code to preload resources here. + // + } +} + +// Called when the app view is activated. Activates the app's CoreWindow. +void ImmersiveView::OnViewActivated(CoreApplicationView const &sender, + IActivatedEventArgs const &) { + // Run() won't start until the CoreWindow is activated. + sender.CoreWindow().Activate(); +} + +void ImmersiveView::OnSuspending( + winrt::Windows::Foundation::IInspectable const &, + SuspendingEventArgs const &args) { + // Save app state asynchronously after requesting a deferral. Holding a + // deferral indicates that the application is busy performing suspending + // operations. Be aware that a deferral may not be held indefinitely; after + // about five seconds, the app will be forced to exit. + SuspendingDeferral deferral = args.SuspendingOperation().GetDeferral(); + + create_task([this, deferral]() { + m_deviceResources->Trim(); + + if (m_main != nullptr) { + m_main->SaveAppState(); + } + + // + // TODO: Insert code here to save your app state. + // + + deferral.Complete(); + }); +} + +void ImmersiveView::OnResuming( + winrt::Windows::Foundation::IInspectable const &, + winrt::Windows::Foundation::IInspectable const &) { + // Restore any data or state that was unloaded on suspend. By default, data + // and state are persisted when resuming from suspend. Note that this event + // does not occur if the app was previously terminated. + + if (m_main != nullptr) { + m_main->LoadAppState(); + } + + // + // TODO: Insert code here to load your app state. + // +} + +// Window event handlers + +void ImmersiveView::OnVisibilityChanged( + CoreWindow const &, VisibilityChangedEventArgs const &args) { + m_windowVisible = args.Visible(); +} + +void ImmersiveView::OnWindowClosed(CoreWindow const &, + CoreWindowEventArgs const &) { + m_windowClosed = true; +} + +// Input event handlers + +void ImmersiveView::OnKeyPressed(CoreWindow const &, KeyEventArgs const &) { + // + // TODO: Bluetooth keyboards are supported by HoloLens. You can use this + // method for + // keyboard input if you want to support it as an optional input method + // for your holographic app. + // +} + +void ImmersiveView::OnPointerPressed(CoreWindow const &, + PointerEventArgs const &) { + // Allow the user to interact with the holographic world using the mouse. + if (m_main != nullptr) { + m_main->OnPointerPressed(); + } +} diff --git a/support/hololens/ServoApp/ImmersiveView.h b/support/hololens/ServoApp/ImmersiveView.h new file mode 100644 index 00000000000..806d267ca59 --- /dev/null +++ b/support/hololens/ServoApp/ImmersiveView.h @@ -0,0 +1,91 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once + +#include "OpenGLES.h" +#include "Common/DeviceResources.h" +#include "ImmersiveMain.h" + +namespace winrt::ServoApp { +// IFrameworkView class. Connects the app with the Windows shell and handles +// application lifecycle events. +class ImmersiveView sealed + : public winrt::implements< + ImmersiveView, + winrt::Windows::ApplicationModel::Core::IFrameworkView> { +public: + // IFrameworkView methods. + void + Initialize(winrt::Windows::ApplicationModel::Core::CoreApplicationView const + &applicationView); + void SetWindow(winrt::Windows::UI::Core::CoreWindow const &window); + void Load(winrt::hstring const &entryPoint); + void Run(); + void Uninitialize(); + +protected: + // Application lifecycle event handlers. + void OnLaunched(winrt::Windows::ApplicationModel::Activation:: + LaunchActivatedEventArgs const &args); + void OnViewActivated( + winrt::Windows::ApplicationModel::Core::CoreApplicationView const &sender, + winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs const + &args); + void OnSuspending( + winrt::Windows::Foundation::IInspectable const &sender, + winrt::Windows::ApplicationModel::SuspendingEventArgs const &args); + void OnResuming(winrt::Windows::Foundation::IInspectable const &sender, + winrt::Windows::Foundation::IInspectable const &args); + + // Window event handlers. + void OnVisibilityChanged( + winrt::Windows::UI::Core::CoreWindow const &sender, + winrt::Windows::UI::Core::VisibilityChangedEventArgs const &args); + void + OnWindowClosed(winrt::Windows::UI::Core::CoreWindow const &sender, + winrt::Windows::UI::Core::CoreWindowEventArgs const &args); + + // CoreWindow input event handlers. + void OnKeyPressed(winrt::Windows::UI::Core::CoreWindow const &sender, + winrt::Windows::UI::Core::KeyEventArgs const &args); + void OnPointerPressed(winrt::Windows::UI::Core::CoreWindow const &sender, + winrt::Windows::UI::Core::PointerEventArgs const &args); + +private: + std::unique_ptr<Immersive::ImmersiveMain> m_main = nullptr; + + std::shared_ptr<DX::DeviceResources> m_deviceResources = nullptr; + bool m_windowClosed = false; + bool m_windowVisible = true; + + // Event registration tokens. + winrt::event_token m_suspendingEventToken; + winrt::event_token m_resumingEventToken; + winrt::event_token m_keyDownEventToken; + winrt::event_token m_pointerPressedEventToken; + winrt::event_token m_windowClosedEventToken; + winrt::event_token m_visibilityChangedEventToken; + + // The holographic space the app will use for rendering. + winrt::Windows::Graphics::Holographic::HolographicSpace m_holographicSpace = + nullptr; + + // FIXME: initialization is done twice: here and in BrowserPage. Share it. + // OpenGLES mOpenGLES; + EGLSurface mRenderSurface{EGL_NO_SURFACE}; +}; + +class ImmersiveViewSource sealed + : public winrt::implements< + ImmersiveViewSource, + winrt::Windows::ApplicationModel::Core::IFrameworkViewSource> { +public: + // IFrameworkViewSource method. + winrt::Windows::ApplicationModel::Core::IFrameworkView CreateView(); + +private: + ImmersiveView holographicView; +}; +} // namespace winrt::ServoApp diff --git a/support/hololens/ServoApp/OpenGLES.cpp b/support/hololens/ServoApp/OpenGLES.cpp new file mode 100644 index 00000000000..31467a4ed60 --- /dev/null +++ b/support/hololens/ServoApp/OpenGLES.cpp @@ -0,0 +1,270 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "pch.h" +#include "logs.h" +#include "OpenGLES.h" + +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; + +OpenGLES::OpenGLES() + : mEglConfig(nullptr), mEglDisplay(EGL_NO_DISPLAY), + mEglContext(EGL_NO_CONTEXT) { + log("OpenGLES::OpenGLES()"); + Initialize(); +} + +OpenGLES::~OpenGLES() { Cleanup(); } + +void OpenGLES::Initialize() { + const EGLint configAttributes[] = {EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_ALPHA_SIZE, + 8, + EGL_DEPTH_SIZE, + 24, + EGL_STENCIL_SIZE, + 8, + EGL_NONE}; + + const EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; + + // Based on Angle MS template. + + const EGLint defaultDisplayAttributes[] = { + // These are the default display attributes, used to request ANGLE's D3D11 + // renderer. + // eglInitialize will only succeed with these attributes if the hardware + // supports D3D11 Feature Level 10_0+. + EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + + // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that + // can have large performance benefits on + // mobile devices. Its syntax is subject to change, though. Please update + // your Visual Studio templates if you + // experience compilation issues with it. + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, + EGL_TRUE, + + // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that + // enables ANGLE to automatically call + // the IDXGIDevice3::Trim method on behalf of the application when it gets + // suspended. + // Calling IDXGIDevice3::Trim when an application is suspended is a + // Windows Store application certification + // requirement. + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, + EGL_TRUE, + EGL_NONE, + }; + + const EGLint fl9_3DisplayAttributes[] = { + // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature + // Level 9_3. + // These attributes are used if the call to eglInitialize fails with the + // default display attributes. + EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, + 9, + EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, + 3, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, + EGL_TRUE, + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, + EGL_TRUE, + EGL_NONE, + }; + + const EGLint warpDisplayAttributes[] = { + // These attributes can be used to request D3D11 WARP. + // They are used if eglInitialize fails with both the default display + // attributes and the 9_3 display attributes. + EGL_PLATFORM_ANGLE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, + EGL_TRUE, + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, + EGL_TRUE, + EGL_NONE, + }; + + // eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. + // It allows us to pass in display attributes, used to configure D3D11. + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = + reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>( + eglGetProcAddress("eglGetPlatformDisplayEXT")); + if (!eglGetPlatformDisplayEXT) { + throw winrt::hresult_error( + E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT"); + } + + // + // To initialize the display, we make three sets of calls to + // eglGetPlatformDisplayEXT and eglInitialize, with varying parameters passed + // to eglGetPlatformDisplayEXT: 1) The first calls uses + // "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 + // Feature Level 10_0+. 2) If eglInitialize fails for step 1 (e.g. because + // 10_0+ isn't supported by the default GPU), then we try again + // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level + // 9_3. + // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by + // the default GPU), then we try again + // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level + // 11_0 on WARP, a D3D11 software rasterizer. + // + + // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above + // comment for details. + mEglDisplay = eglGetPlatformDisplayEXT( + EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); + if (mEglDisplay == EGL_NO_DISPLAY) { + throw winrt::hresult_error(E_FAIL, L"Failed to get EGL display"); + } + + if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) { + // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is + // unavailable (e.g. on some mobile devices). + mEglDisplay = eglGetPlatformDisplayEXT( + EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes); + if (mEglDisplay == EGL_NO_DISPLAY) { + throw winrt::hresult_error(E_FAIL, L"Failed to get EGL display"); + } + + if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) { + // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is + // unavailable on the default GPU. + mEglDisplay = eglGetPlatformDisplayEXT( + EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes); + if (mEglDisplay == EGL_NO_DISPLAY) { + throw winrt::hresult_error(E_FAIL, L"Failed to get EGL display"); + } + + if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) { + // If all of the calls to eglInitialize returned EGL_FALSE then an error + // has occurred. + throw winrt::hresult_error(E_FAIL, L"Failed to initialize EGL"); + } + } + } + + EGLint numConfigs = 0; + if ((eglChooseConfig(mEglDisplay, configAttributes, &mEglConfig, 1, + &numConfigs) == EGL_FALSE) || + (numConfigs == 0)) { + throw winrt::hresult_error(E_FAIL, L"Failed to choose first EGLConfig"); + } + + mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, + contextAttributes); + if (mEglContext == EGL_NO_CONTEXT) { + throw winrt::hresult_error(E_FAIL, L"Failed to create EGL context"); + } +} + +void OpenGLES::Cleanup() { + if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT) { + eglDestroyContext(mEglDisplay, mEglContext); + mEglContext = EGL_NO_CONTEXT; + } + + if (mEglDisplay != EGL_NO_DISPLAY) { + eglTerminate(mEglDisplay); + mEglDisplay = EGL_NO_DISPLAY; + } +} + +void OpenGLES::Reset() { + Cleanup(); + Initialize(); +} + +// FIXME: simplify this. Duplicating code with CreateSurface(SwapChainPanel) +EGLSurface +OpenGLES::CreateSurface(winrt::Windows::UI::Core::CoreWindow const &cwin) { + EGLSurface surface = EGL_NO_SURFACE; + + const EGLint surfaceAttributes[] = {EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, + EGL_TRUE, EGL_NONE}; + + PropertySet surfaceCreationProperties; + + surfaceCreationProperties.Insert(EGLNativeWindowTypeProperty, cwin); + // How to set size and or scale: + // Insert(EGLRenderSurfaceSizeProperty), + // PropertyValue::CreateSize(*renderSurfaceSize)); + // Insert(EGLRenderResolutionScaleProperty), + // PropertyValue::CreateSingle(*resolutionScale)); + + EGLNativeWindowType win = static_cast<EGLNativeWindowType>( + winrt::get_abi(surfaceCreationProperties)); + surface = + eglCreateWindowSurface(mEglDisplay, mEglConfig, win, surfaceAttributes); + + if (surface == EGL_NO_SURFACE) { + throw winrt::hresult_error(E_FAIL, L"Failed to create EGL surface"); + } + + return surface; +} + +EGLSurface OpenGLES::CreateSurface(SwapChainPanel const &panel) { + EGLSurface surface = EGL_NO_SURFACE; + + const EGLint surfaceAttributes[] = {EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, + EGL_TRUE, EGL_NONE}; + + PropertySet surfaceCreationProperties; + + surfaceCreationProperties.Insert(EGLNativeWindowTypeProperty, panel); + // How to set size and or scale: + // Insert(EGLRenderSurfaceSizeProperty), + // PropertyValue::CreateSize(*renderSurfaceSize)); + // Insert(EGLRenderResolutionScaleProperty), + // PropertyValue::CreateSingle(*resolutionScale)); + + EGLNativeWindowType win = static_cast<EGLNativeWindowType>( + winrt::get_abi(surfaceCreationProperties)); + surface = + eglCreateWindowSurface(mEglDisplay, mEglConfig, win, surfaceAttributes); + + if (surface == EGL_NO_SURFACE) { + throw winrt::hresult_error(E_FAIL, L"Failed to create EGL surface"); + } + + return surface; +} + +void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint *width, + EGLint *height) { + eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); + eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); +} + +void OpenGLES::DestroySurface(const EGLSurface surface) { + if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) { + eglDestroySurface(mEglDisplay, surface); + } +} + +void OpenGLES::MakeCurrent(const EGLSurface surface) { + if (eglMakeCurrent(mEglDisplay, surface, surface, mEglContext) == EGL_FALSE) { + throw winrt::hresult_error(E_FAIL, L"Failed to make EGLSurface current"); + } +} + +EGLBoolean OpenGLES::SwapBuffers(const EGLSurface surface) { + return (eglSwapBuffers(mEglDisplay, surface)); +} diff --git a/support/hololens/ServoApp/OpenGLES.h b/support/hololens/ServoApp/OpenGLES.h new file mode 100644 index 00000000000..6d17798acf1 --- /dev/null +++ b/support/hololens/ServoApp/OpenGLES.h @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once + +class OpenGLES { +public: + OpenGLES(); + ~OpenGLES(); + + EGLSurface + CreateSurface(winrt::Windows::UI::Xaml::Controls::SwapChainPanel const &); + EGLSurface CreateSurface(winrt::Windows::UI::Core::CoreWindow const &); + + void GetSurfaceDimensions(const EGLSurface surface, EGLint *width, + EGLint *height); + void DestroySurface(const EGLSurface surface); + void MakeCurrent(const EGLSurface surface); + EGLBoolean SwapBuffers(const EGLSurface surface); + void Reset(); + +private: + void Initialize(); + void Cleanup(); + +private: + EGLDisplay mEglDisplay = EGL_NO_DISPLAY; + EGLContext mEglContext = nullptr; + EGLConfig mEglConfig = nullptr; +}; diff --git a/support/hololens/ServoApp/Package.appxmanifest b/support/hololens/ServoApp/Package.appxmanifest new file mode 100644 index 00000000000..c437822284c --- /dev/null +++ b/support/hololens/ServoApp/Package.appxmanifest @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp"> + <Identity + Name="1d265729-8836-4bd3-9992-4cb111d1068b" + Publisher="CN=paul" + Version="1.0.0.0" /> + <mp:PhoneIdentity PhoneProductId="1d265729-8836-4bd3-9992-4cb111d1068b" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> + <Properties> + <DisplayName>ServoApp</DisplayName> + <PublisherDisplayName>paul</PublisherDisplayName> + <Logo>Assets\StoreLogo.png</Logo> + </Properties> + <Dependencies> + <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" /> + </Dependencies> + <Resources> + <Resource Language="x-generate" /> + </Resources> + <Applications> + <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="ServoApp.App"> + <uap:VisualElements DisplayName="ServoApp" Description="Project for a single page C++/WinRT Universal Windows Platform (UWP) app with no predefined layout" + Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" BackgroundColor="transparent"> + <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"> + </uap:DefaultTile> + <uap:SplashScreen Image="Assets\SplashScreen.png" /> + </uap:VisualElements> + </Application> + </Applications> + <Capabilities> + <Capability Name="internetClient" /> + </Capabilities> +</Package> diff --git a/support/hololens/ServoApp/PropertySheet.props b/support/hololens/ServoApp/PropertySheet.props new file mode 100644 index 00000000000..5942ba395bb --- /dev/null +++ b/support/hololens/ServoApp/PropertySheet.props @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <!-- + To customize common C++/WinRT project properties: + * right-click the project node + * expand the Common Properties item + * select the C++/WinRT property page + + For more advanced scenarios, and complete documentation, please see: + https://github.com/Microsoft/xlang/tree/master/src/package/cppwinrt/nuget + --> + <PropertyGroup /> + <ItemDefinitionGroup /> +</Project>
\ No newline at end of file diff --git a/support/hololens/ServoApp/Servo.cpp b/support/hololens/ServoApp/Servo.cpp new file mode 100644 index 00000000000..8ffd2258a71 --- /dev/null +++ b/support/hololens/ServoApp/Servo.cpp @@ -0,0 +1,95 @@ +#include "pch.h" +#include "Servo.h" + +void on_load_started() {} +void on_load_ended() {} +void on_history_changed(bool, bool) {} +void on_shutdown_complete() {} + +std::function<void()> Servo::sFlush = []() {}; +std::function<void()> Servo::sMakeCurrent = []() {}; +std::function<void()> Servo::sWakeUp = []() {}; +std::function<void(std::wstring const &)> Servo::sOnAlert = + [](std::wstring const &) {}; +std::function<void(std::wstring const &)> Servo::sOnTitleChanged = + [](std::wstring const &) {}; +std::function<void(std::wstring const &)> Servo::sOnURLChanged = + [](std::wstring const &) {}; + +bool Servo::sAnimating = false; + +std::wstring char2w(const char *c_str) { + auto str = std::string(c_str); + int size_needed = + MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); + std::wstring str2(size_needed, 0); + MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &str2[0], + size_needed); + return str2; +} + +void on_alert(const char *message) { Servo::sOnAlert(char2w(message)); } + +void on_title_changed(const char *title) { + Servo::sOnTitleChanged(char2w(title)); +} + +void on_url_changed(const char *url) { Servo::sOnURLChanged(char2w(url)); } + +void flush() { Servo::sFlush(); } + +void make_current() { Servo::sMakeCurrent(); } + +void wakeup() { Servo::sWakeUp(); } + +bool on_allow_navigation(const char *url) { return true; }; + +void on_animating_changed(bool aAnimating) { Servo::sAnimating = aAnimating; } + +Servo::Servo(GLsizei width, GLsizei height) + : mAnimating(false), mWindowHeight(height), mWindowWidth(width) { + + CInitOptions o; + o.args = NULL; + o.url = "https://google.com"; + o.width = mWindowWidth; + o.height = mWindowHeight; + o.density = 1.0; + o.enable_subpixel_text_antialiasing = false; + o.vr_pointer = NULL; + + CHostCallbacks c; + c.flush = &flush; + c.make_current = &make_current; + c.on_alert = &on_alert; + c.on_load_started = &on_load_started; + c.on_load_ended = &on_load_ended; + c.on_title_changed = &on_title_changed; + c.on_url_changed = &on_url_changed; + c.on_history_changed = &on_history_changed; + c.on_animating_changed = &on_animating_changed; + c.on_shutdown_complete = &on_shutdown_complete; + c.on_allow_navigation = &on_allow_navigation; + + init_with_egl(o, &wakeup, c); +} + +Servo::~Servo() { deinit(); } + +void Servo::PerformUpdates() { perform_updates(); } + +void Servo::SetBatchMode(bool mode) { set_batch_mode(mode); } + +void Servo::GoForward() { go_forward(); } + +void Servo::GoBack() { go_back(); } + +void Servo::SetSize(GLsizei width, GLsizei height) { + if (width != mWindowWidth || height != mWindowHeight) { + mWindowWidth = width; + mWindowHeight = height; + resize(mWindowWidth, mWindowHeight); + } +} + +void Servo::Click(float x, float y) { click(x, y); } diff --git a/support/hololens/ServoApp/Servo.h b/support/hololens/ServoApp/Servo.h new file mode 100644 index 00000000000..118a6ab517c --- /dev/null +++ b/support/hololens/ServoApp/Servo.h @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once + +#include "pch.h" + +extern "C" { +#include <simpleservo.h> +} + +class Servo { +public: + Servo(GLsizei width, GLsizei height); + ~Servo(); + void PerformUpdates(); + void Click(float, float); + void SetSize(GLsizei width, GLsizei height); + void SetBatchMode(bool); + void GoBack(); + void GoForward(); + + // Static lambas called by Servo callbacks. + + // Will be called from any thead + static std::function<void()> sWakeUp; + // Will be called from GL thread + static std::function<void()> sFlush; + static std::function<void()> sMakeCurrent; + static std::function<void(std::wstring const &)> sOnAlert; + static std::function<void(std::wstring const &)> sOnTitleChanged; + static std::function<void(std::wstring const &)> sOnURLChanged; + static bool sAnimating; + +private: + GLsizei mWindowWidth; + GLsizei mWindowHeight; + bool mAnimating; +}; diff --git a/support/hololens/ServoApp/ServoApp.vcxproj b/support/hololens/ServoApp/ServoApp.vcxproj new file mode 100644 index 00000000000..fcfb8e67c13 --- /dev/null +++ b/support/hololens/ServoApp/ServoApp.vcxproj @@ -0,0 +1,574 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.props')" /> + <PropertyGroup Label="Globals"> + <CppWinRTOptimized>true</CppWinRTOptimized> + <MinimalCoreWin>true</MinimalCoreWin> + <ProjectGuid>{0eab7d8b-97fd-4c92-8bb2-d5691b3d5abd}</ProjectGuid> + <ProjectName>ServoApp</ProjectName> + <RootNamespace>ServoApp</RootNamespace> + <DefaultLanguage>en-US</DefaultLanguage> + <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion> + <AppContainerApplication>true</AppContainerApplication> + <ApplicationType>Windows Store</ApplicationType> + <ApplicationTypeRevision>10.0</ApplicationTypeRevision> + <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM"> + <Configuration>Debug</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM"> + <Configuration>Release</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <UseDebugLibraries>true</UseDebugLibraries> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="PropertySheet.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <PackageCertificateKeyFile>ServoApp_TemporaryKey.pfx</PackageCertificateKeyFile> + <PackageCertificateThumbprint>1132EA939A7107B303D4D40ED6CE28778FC96409</PackageCertificateThumbprint> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <WarningLevel>Level4</WarningLevel> + <AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions> + <!--Temporarily disable cppwinrt heap enforcement to work around xaml compiler generated std::shared_ptr use --> + <AdditionalOptions Condition="'$(CppWinRTHeapEnforcement)'==''">/DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)</AdditionalOptions> + <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'"> + <ClCompile> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\..\..\..\target\debug\</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\..\..\..\target\debug\</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\..\..\..\target\debug\</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">WindowsApp.lib;%(AdditionalDependencies);simpleservo.dll.lib</AdditionalDependencies> + </Link> + <Link> + <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WindowsApp.lib;%(AdditionalDependencies);simpleservo.dll.lib</AdditionalDependencies> + </Link> + <Link> + <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WindowsApp.lib;%(AdditionalDependencies);simpleservo.dll.lib</AdditionalDependencies> + <AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)\..\..\..\target\debug\</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> + <ClCompile> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\..\..\..\target\release</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\..\..\..\target\release</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories);$(ProjectDir)\..\..\..\target\release</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">WindowsApp.lib;%(AdditionalDependencies);simpleservo.dll.lib</AdditionalDependencies> + </Link> + <Link> + <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WindowsApp.lib;%(AdditionalDependencies);simpleservo.dll.lib</AdditionalDependencies> + </Link> + <Link> + <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WindowsApp.lib;%(AdditionalDependencies);simpleservo.dll.lib</AdditionalDependencies> + <AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)\..\..\..\target\release\</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="Common\CameraResources.h" /> + <ClInclude Include="Common\DeviceResources.h" /> + <ClInclude Include="Common\DirectXHelper.h" /> + <ClInclude Include="Common\StepTimer.h" /> + <ClInclude Include="Content\ShaderStructures.h" /> + <ClInclude Include="Content\SpatialInputHandler.h" /> + <ClInclude Include="Content\SpinningCubeRenderer.h" /> + <ClInclude Include="ImmersiveMain.h" /> + <ClInclude Include="ImmersiveView.h" /> + <ClInclude Include="logs.h" /> + <ClInclude Include="OpenGLES.h" /> + <ClInclude Include="pch.h" /> + <ClInclude Include="App.h"> + <DependentUpon>App.xaml</DependentUpon> + </ClInclude> + <ClInclude Include="BrowserPage.h"> + <DependentUpon>BrowserPage.xaml</DependentUpon> + </ClInclude> + <ClInclude Include="Servo.h" /> + </ItemGroup> + <ItemGroup> + <ApplicationDefinition Include="App.xaml"> + <SubType>Designer</SubType> + </ApplicationDefinition> + <Page Include="BrowserPage.xaml"> + <SubType>Designer</SubType> + </Page> + </ItemGroup> + <ItemGroup> + <AppxManifest Include="Package.appxmanifest"> + <SubType>Designer</SubType> + </AppxManifest> + <None Include="..\..\..\target\debug\api-ms-win-crt-runtime-l1-1-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\avcodec-58.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\avfilter-7.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\avformat-58.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\avutil-56.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\bz2.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\ffi-7.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gio-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\glib-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gmodule-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gobject-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstapp-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstapp.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstaudio-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstaudioconvert.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstaudiofx.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstaudioparsers.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstaudioresample.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstautodetect.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstbase-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstcodecparsers-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstcontroller-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstcoreelements.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstdeinterlace.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstfft-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstgl-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstinterleave.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstisomp4.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstlibav.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstpbutils-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstplayback.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstplayer-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstproxy.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstreamer-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstriff-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstrtp-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstsdp-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gsttag-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gsttypefindfunctions.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstvideo-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstvideoconvert.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstvideofilter.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstvideoparsersbad.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstvideoscale.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstvolume.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstwasapi.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\gstwebrtc-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\intl-8.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\libeay32.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\libwinpthread-1.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\msvcp140.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\orc-0.4-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\simpleservo.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\ssleay32.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\swresample-3.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\vcruntime140.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\debug\z-1.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\api-ms-win-crt-runtime-l1-1-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\avcodec-58.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\avfilter-7.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\avformat-58.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\avutil-56.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\bz2.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\ffi-7.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gio-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\glib-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gmodule-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gobject-2.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstapp-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstapp.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstaudio-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstaudioconvert.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstaudiofx.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstaudioparsers.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstaudioresample.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstautodetect.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstbase-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstcodecparsers-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstcontroller-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstcoreelements.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstdeinterlace.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstfft-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstgl-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstinterleave.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstisomp4.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstlibav.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstpbutils-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstplayback.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstplayer-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstproxy.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstreamer-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstriff-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstrtp-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstsdp-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gsttag-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gsttypefindfunctions.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstvideo-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstvideoconvert.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstvideofilter.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstvideoparsersbad.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstvideoscale.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstvolume.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstwasapi.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\gstwebrtc-1.0-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\intl-8.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\libeay32.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\libwinpthread-1.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\msvcp140.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\orc-0.4-0.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\simpleservo.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\ssleay32.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\swresample-3.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\vcruntime140.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="..\..\..\target\release\z-1.dll"> + <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent> + </None> + <None Include="ServoApp_TemporaryKey.pfx" /> + </ItemGroup> + <ItemGroup> + <Image Include="Assets\LockScreenLogo.scale-200.png" /> + <Image Include="Assets\SplashScreen.scale-200.png" /> + <Image Include="Assets\Square150x150Logo.scale-200.png" /> + <Image Include="Assets\Square44x44Logo.scale-200.png" /> + <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" /> + <Image Include="Assets\StoreLogo.png" /> + <Image Include="Assets\Wide310x150Logo.scale-200.png" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Common\CameraResources.cpp" /> + <ClCompile Include="Common\DeviceResources.cpp" /> + <ClCompile Include="Content\SpatialInputHandler.cpp" /> + <ClCompile Include="Content\SpinningCubeRenderer.cpp" /> + <ClCompile Include="ImmersiveMain.cpp" /> + <ClCompile Include="ImmersiveView.cpp" /> + <ClCompile Include="OpenGLES.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader>Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="App.cpp"> + <DependentUpon>App.xaml</DependentUpon> + </ClCompile> + <ClCompile Include="BrowserPage.cpp"> + <DependentUpon>BrowserPage.xaml</DependentUpon> + </ClCompile> + <ClCompile Include="$(GeneratedFilesDir)module.g.cpp" /> + <ClCompile Include="logs.cpp" /> + <ClCompile Include="Servo.cpp" /> + </ItemGroup> + <ItemGroup> + <Midl Include="App.idl"> + <DependentUpon>App.xaml</DependentUpon> + </Midl> + <Midl Include="BrowserPage.idl"> + <DependentUpon>BrowserPage.xaml</DependentUpon> + </Midl> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + <None Include="PropertySheet.props" /> + </ItemGroup> + <ItemGroup> + <FxCompile Include="Content\PixelShader.hlsl"> + <ShaderType>Pixel</ShaderType> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <None Include="Content\VertexShaderShared.hlsl" /> + <FxCompile Include="Content\VertexShader.hlsl"> + <ShaderType>Vertex</ShaderType> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile Include="Content\VPRTVertexShader.hlsl"> + <ShaderType>Vertex</ShaderType> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + <FxCompile Include="Content\GeometryShader.hlsl"> + <ShaderType>Geometry</ShaderType> + <ShaderModel>5.0</ShaderModel> + </FxCompile> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + <Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" /> + <Import Project="..\packages\ANGLE.WindowsStore.2.1.13\build\native\ANGLE.WindowsStore.targets" Condition="Exists('..\packages\ANGLE.WindowsStore.2.1.13\build\native\ANGLE.WindowsStore.targets')" /> + </ImportGroup> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>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}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.props'))" /> + <Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190620.2\build\native\Microsoft.Windows.CppWinRT.targets'))" /> + <Error Condition="!Exists('..\packages\ANGLE.WindowsStore.2.1.13\build\native\ANGLE.WindowsStore.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ANGLE.WindowsStore.2.1.13\build\native\ANGLE.WindowsStore.targets'))" /> + </Target> +</Project>
\ No newline at end of file diff --git a/support/hololens/ServoApp/ServoApp.vcxproj.filters b/support/hololens/ServoApp/ServoApp.vcxproj.filters new file mode 100644 index 00000000000..604bb785585 --- /dev/null +++ b/support/hololens/ServoApp/ServoApp.vcxproj.filters @@ -0,0 +1,476 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Midl Include="BrowserPage.idl" /> + <Midl Include="App.idl" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pch.cpp" /> + <ClCompile Include="$(GeneratedFilesDir)module.g.cpp" /> + <ClCompile Include="logs.cpp" /> + <ClCompile Include="ImmersiveView.cpp" /> + <ClCompile Include="BrowserPage.cpp" /> + <ClCompile Include="Servo.cpp" /> + <ClCompile Include="OpenGLES.cpp" /> + <ClCompile Include="App.cpp" /> + <ClCompile Include="Common\CameraResources.cpp"> + <Filter>Common</Filter> + </ClCompile> + <ClCompile Include="Common\DeviceResources.cpp"> + <Filter>Common</Filter> + </ClCompile> + <ClCompile Include="Content\SpatialInputHandler.cpp"> + <Filter>Content</Filter> + </ClCompile> + <ClCompile Include="Content\SpinningCubeRenderer.cpp"> + <Filter>Content</Filter> + </ClCompile> + <ClCompile Include="ImmersiveMain.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="pch.h" /> + <ClInclude Include="logs.h" /> + <ClInclude Include="ImmersiveView.h" /> + <ClInclude Include="BrowserPage.h" /> + <ClInclude Include="Servo.h" /> + <ClInclude Include="OpenGLES.h" /> + <ClInclude Include="App.h" /> + <ClInclude Include="Common\CameraResources.h"> + <Filter>Common</Filter> + </ClInclude> + <ClInclude Include="Common\DeviceResources.h"> + <Filter>Common</Filter> + </ClInclude> + <ClInclude Include="Common\DirectXHelper.h"> + <Filter>Common</Filter> + </ClInclude> + <ClInclude Include="Common\StepTimer.h"> + <Filter>Common</Filter> + </ClInclude> + <ClInclude Include="Content\ShaderStructures.h"> + <Filter>Content</Filter> + </ClInclude> + <ClInclude Include="Content\SpatialInputHandler.h"> + <Filter>Content</Filter> + </ClInclude> + <ClInclude Include="Content\SpinningCubeRenderer.h"> + <Filter>Content</Filter> + </ClInclude> + <ClInclude Include="ImmersiveMain.h" /> + </ItemGroup> + <ItemGroup> + <Image Include="Assets\Wide310x150Logo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\StoreLogo.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\Square150x150Logo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\Square44x44Logo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\SplashScreen.scale-200.png"> + <Filter>Assets</Filter> + </Image> + <Image Include="Assets\LockScreenLogo.scale-200.png"> + <Filter>Assets</Filter> + </Image> + </ItemGroup> + <ItemGroup> + <AppxManifest Include="Package.appxmanifest" /> + </ItemGroup> + <ItemGroup> + <None Include="ServoApp_TemporaryKey.pfx" /> + <None Include="packages.config" /> + <None Include="Content\VertexShaderShared.hlsl"> + <Filter>Content</Filter> + </None> + <None Include="..\..\..\target\debug\api-ms-win-crt-runtime-l1-1-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\avcodec-58.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\avfilter-7.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\avformat-58.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\avutil-56.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\bz2.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\ffi-7.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gio-2.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\glib-2.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gmodule-2.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gobject-2.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstapp.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstapp-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstaudio-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstaudioconvert.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstaudiofx.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstaudioparsers.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstaudioresample.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstautodetect.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstbase-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstcodecparsers-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstcontroller-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstcoreelements.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstdeinterlace.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstfft-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstgl-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstinterleave.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstisomp4.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstlibav.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstpbutils-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstplayback.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstplayer-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstproxy.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstreamer-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstriff-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstrtp-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstsdp-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gsttag-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gsttypefindfunctions.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstvideo-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstvideoconvert.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstvideofilter.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstvideoparsersbad.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstvideoscale.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstvolume.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstwasapi.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\gstwebrtc-1.0-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\intl-8.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\libeay32.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\libwinpthread-1.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\msvcp140.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\orc-0.4-0.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\ssleay32.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\swresample-3.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\vcruntime140.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\z-1.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\z-1.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\vcruntime140.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\swresample-3.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\ssleay32.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\simpleservo.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\orc-0.4-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\msvcp140.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\libwinpthread-1.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\libeay32.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\intl-8.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstwebrtc-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstwasapi.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstvolume.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstvideoscale.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstvideoparsersbad.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstvideofilter.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstvideoconvert.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstvideo-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gsttypefindfunctions.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gsttag-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstsdp-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstrtp-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstriff-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstreamer-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstproxy.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstplayer-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstplayback.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstpbutils-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstlibav.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstisomp4.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstinterleave.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstgl-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstfft-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstdeinterlace.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstcoreelements.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstcontroller-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstcodecparsers-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstbase-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstautodetect.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstaudioresample.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstaudioparsers.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstaudiofx.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstaudioconvert.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstaudio-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstapp-1.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gstapp.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gobject-2.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gmodule-2.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\glib-2.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\gio-2.0-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\ffi-7.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\bz2.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\avutil-56.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\avformat-58.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\avfilter-7.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\avcodec-58.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\release\api-ms-win-crt-runtime-l1-1-0.dll"> + <Filter>ReleaseServoDLLs</Filter> + </None> + <None Include="..\..\..\target\debug\simpleservo.dll"> + <Filter>DebugServoDLLs</Filter> + </None> + </ItemGroup> + <ItemGroup> + <Filter Include="Assets"> + <UniqueIdentifier>{e48dc53e-40b1-40cb-970a-f89935452892}</UniqueIdentifier> + </Filter> + <Filter Include="DebugServoDLLs"> + <UniqueIdentifier>{6c943d94-ac99-4fb1-825f-233a21441ae7}</UniqueIdentifier> + </Filter> + <Filter Include="ReleaseServoDLLs"> + <UniqueIdentifier>{663f48bc-21ec-4f00-9db5-cd0a5fa87983}</UniqueIdentifier> + </Filter> + <Filter Include="Common"> + <UniqueIdentifier>{e6c0d90c-587b-446e-a6a7-037217d03006}</UniqueIdentifier> + </Filter> + <Filter Include="Content"> + <UniqueIdentifier>{83d6e7af-b929-4869-804e-571256af2969}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <None Include="PropertySheet.props" /> + </ItemGroup> + <ItemGroup> + <Page Include="BrowserPage.xaml" /> + </ItemGroup> + <ItemGroup> + <FxCompile Include="Content\GeometryShader.hlsl"> + <Filter>Content</Filter> + </FxCompile> + <FxCompile Include="Content\PixelShader.hlsl"> + <Filter>Content</Filter> + </FxCompile> + <FxCompile Include="Content\VertexShader.hlsl"> + <Filter>Content</Filter> + </FxCompile> + <FxCompile Include="Content\VPRTVertexShader.hlsl"> + <Filter>Content</Filter> + </FxCompile> + </ItemGroup> + <ItemGroup> + <ApplicationDefinition Include="App.xaml" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/support/hololens/ServoApp/logs.cpp b/support/hololens/ServoApp/logs.cpp new file mode 100644 index 00000000000..854684e6c20 --- /dev/null +++ b/support/hololens/ServoApp/logs.cpp @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "pch.h" + +void log(const char *format, ...) { + char buf[4096], *p = buf; + va_list args; + int n; + + va_start(args, format); + n = vsnprintf(p, sizeof buf - 3, format, args); + va_end(args); + + p += (n < 0) ? sizeof buf - 3 : n; + + while (p > buf && isspace(p[-1])) { + *--p = '\0'; + } + + *p++ = '\r'; + *p++ = '\n'; + *p = '\0'; + + OutputDebugStringA(buf); +}
\ No newline at end of file diff --git a/support/hololens/ServoApp/logs.h b/support/hololens/ServoApp/logs.h new file mode 100644 index 00000000000..d71fd3e1233 --- /dev/null +++ b/support/hololens/ServoApp/logs.h @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#pragma once + +void log(const char *format, ...);
\ No newline at end of file diff --git a/support/hololens/ServoApp/packages.config b/support/hololens/ServoApp/packages.config new file mode 100644 index 00000000000..b3c6a3cc0c6 --- /dev/null +++ b/support/hololens/ServoApp/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="ANGLE.WindowsStore" version="2.1.13" targetFramework="native" /> + <package id="Microsoft.Windows.CppWinRT" version="2.0.190620.2" targetFramework="native" /> +</packages>
\ No newline at end of file diff --git a/support/hololens/ServoApp/pch.cpp b/support/hololens/ServoApp/pch.cpp new file mode 100644 index 00000000000..bcb5590be1b --- /dev/null +++ b/support/hololens/ServoApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/support/hololens/ServoApp/pch.h b/support/hololens/ServoApp/pch.h new file mode 100644 index 00000000000..c8689fab90e --- /dev/null +++ b/support/hololens/ServoApp/pch.h @@ -0,0 +1,52 @@ +#pragma once + +#include <future> +#include <hstring.h> +#include <map> +#include <mutex> +#include <restrictederrorinfo.h> +#include <unknwn.h> +#include <vector> +#include <wincodec.h> +#include <array> +#include <d2d1_2.h> +#include <d3d11_4.h> +#include <DirectXColors.h> +#include <dwrite_2.h> +#include <Windows.Graphics.Directx.Direct3D11.Interop.h> +#include <windows.h> +#include <WindowsNumerics.h> +#include <wrl/client.h> + +#define GL_GLEXT_PROTOTYPES +#include <angle_windowsstore.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <EGL/eglplatform.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <winrt/Windows.ApplicationModel.Activation.h> +#include <winrt/Windows.ApplicationModel.Core.h> +#include <winrt/Windows.Foundation.Collections.h> +#include <winrt/Windows.Foundation.h> +#include <winrt/Windows.Foundation.Metadata.h> +#include <winrt/Windows.Gaming.Input.h> +#include <winrt/Windows.Graphics.Display.h> +#include <winrt/Windows.Graphics.Holographic.h> +#include <winrt/Windows.Perception.People.h> +#include <winrt/Windows.Perception.Spatial.h> +#include <winrt/Windows.Storage.h> +#include <winrt/Windows.Storage.Streams.h> +#include <winrt/Windows.UI.Core.h> +#include <winrt/Windows.UI.Input.Spatial.h> +#include "winrt/Windows.UI.Popups.h" +#include "winrt/Windows.UI.ViewManagement.h" +#include <winrt/Windows.UI.Xaml.Controls.h> +#include <winrt/Windows.UI.Xaml.Controls.Primitives.h> +#include <winrt/Windows.UI.Xaml.Data.h> +#include <winrt/Windows.UI.Xaml.h> +#include "winrt/Windows.UI.Xaml.Input.h" +#include <winrt/Windows.UI.Xaml.Interop.h> +#include <winrt/Windows.UI.Xaml.Markup.h> +#include <winrt/Windows.UI.Xaml.Navigation.h> |