2 // Copyright (c) Microsoft. All rights reserved.
3 // This code is licensed under the MIT License (MIT).
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 // Developed by Minigraph
11 // Author: James Stanard
16 #include "GraphicsCore.h"
17 #include "SystemTime.h"
18 #include "GameInput.h"
19 #include "BufferManager.h"
20 #include "CommandContext.h"
21 #include "PostEffects.h"
23 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
24 #pragma comment(lib, "runtimeobject.lib")
27 using namespace Windows::ApplicationModel
;
28 using namespace Windows::UI::Core
;
29 using namespace Windows::UI::ViewManagement
;
30 using Windows::ApplicationModel::Core::CoreApplication
;
31 using Windows::ApplicationModel::Core::CoreApplicationView
;
32 using Windows::ApplicationModel::Activation::IActivatedEventArgs
;
33 using Windows::Foundation::TypedEventHandler
;
38 extern ColorBuffer g_GenMipsBuffer
;
43 using namespace Graphics
;
44 const bool TestGenerateMips
= false;
46 void InitializeApplication( IGameApp
& game
)
48 Graphics::Initialize();
49 SystemTime::Initialize();
50 GameInput::Initialize();
51 EngineTuning::Initialize();
56 void TerminateApplication( IGameApp
& game
)
60 GameInput::Shutdown();
63 bool UpdateApplication( IGameApp
& game
)
65 EngineProfiling::Update();
67 float DeltaTime
= Graphics::GetFrameTime();
69 GameInput::Update(DeltaTime
);
70 EngineTuning::Update(DeltaTime
);
72 game
.Update(DeltaTime
);
75 PostEffects::Render();
79 GraphicsContext
& MipsContext
= GraphicsContext::Begin();
81 // Exclude from timings this copy necessary to setup the test
82 MipsContext
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_GENERIC_READ
);
83 MipsContext
.TransitionResource(g_GenMipsBuffer
, D3D12_RESOURCE_STATE_COPY_DEST
);
84 MipsContext
.CopySubresource(g_GenMipsBuffer
, 0, g_SceneColorBuffer
, 0);
86 EngineProfiling::BeginBlock(L
"GenerateMipMaps()", &MipsContext
);
87 g_GenMipsBuffer
.GenerateMipMaps(MipsContext
);
88 EngineProfiling::EndBlock(&MipsContext
);
93 GraphicsContext
& UiContext
= GraphicsContext::Begin(L
"Render UI");
94 UiContext
.TransitionResource(g_OverlayBuffer
, D3D12_RESOURCE_STATE_RENDER_TARGET
, true);
95 UiContext
.ClearColor(g_OverlayBuffer
);
96 UiContext
.SetRenderTarget(g_OverlayBuffer
.GetRTV());
97 UiContext
.SetViewportAndScissor(0, 0, g_OverlayBuffer
.GetWidth(), g_OverlayBuffer
.GetHeight());
98 game
.RenderUI(UiContext
);
100 EngineTuning::Display( UiContext
, 10.0f
, 40.0f
, 1900.0f
, 1040.0f
);
106 return !game
.IsDone();
109 // Default implementation to be overridden by the application
110 bool IGameApp::IsDone( void )
112 return GameInput::IsFirstPressed(GameInput::kKey_escape
);
115 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
117 Platform::Agile
<CoreWindow
> g_window
;
119 ref
class MyApplicationView sealed
: public Core::IFrameworkView
122 MyApplicationView() {}
124 // IFrameworkView Methods.
125 virtual void Initialize(CoreApplicationView
^ applicationView
);
126 virtual void Load(Platform::String
^ entryPoint
);
127 virtual void Run(void);
128 virtual void SetWindow(CoreWindow
^ window
);
129 virtual void Uninitialize(void);
133 void OnActivated(Core::CoreApplicationView
^ applicationView
, Activation::IActivatedEventArgs
^ args
);
134 void OnSuspending(Platform::Object
^ sender
, SuspendingEventArgs
^ args
);
135 void OnResuming(Platform::Object
^ sender
, Platform::Object
^ args
);
136 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
137 void OnWindowSizeChanged(CoreWindow
^ sender
, WindowSizeChangedEventArgs
^ args
);
138 void OnWindowClosed(CoreWindow
^ sender
, CoreWindowEventArgs
^ args
);
139 void OnVisibilityChanged(CoreWindow
^ sender
, VisibilityChangedEventArgs
^ args
);
140 void OnPointerPressed(CoreWindow
^ sender
, PointerEventArgs
^ args
);
141 void OnPointerMoved(CoreWindow
^ sender
, PointerEventArgs
^ args
);
142 void OnKeyDown(CoreWindow
^ sender
, KeyEventArgs
^ args
);
143 void OnKeyUp(CoreWindow
^ sender
, KeyEventArgs
^ args
);
148 bool m_windowVisible
;
149 volatile bool m_IsRunning
;
150 volatile bool m_IsCapturingPointer
;
151 float m_PointerX
, m_PointerY
;
154 ref
class ApplicationViewSource sealed
: Core::IFrameworkViewSource
157 virtual Core::IFrameworkView
^ CreateView()
159 return ref
new MyApplicationView();
164 // Called by the system. Perform application initialization here, hooking application wide events, etc.
165 void MyApplicationView::Initialize(CoreApplicationView
^ applicationView
)
167 applicationView
->Activated
+= ref
new TypedEventHandler
<CoreApplicationView
^, IActivatedEventArgs
^>(this, &MyApplicationView::OnActivated
);
170 // Called when we are provided a window.
171 void MyApplicationView::SetWindow(CoreWindow
^ window
)
173 // We record the window pointer now, but you can also call this function to retrieve it:
174 // CoreWindow::GetForCurrentThread()
177 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
178 window
->SizeChanged
+= ref
new TypedEventHandler
<CoreWindow
^, WindowSizeChangedEventArgs
^>(this, &MyApplicationView::OnWindowSizeChanged
);
179 window
->VisibilityChanged
+= ref
new TypedEventHandler
<CoreWindow
^, VisibilityChangedEventArgs
^>(this, &MyApplicationView::OnVisibilityChanged
);
180 window
->Closed
+= ref
new TypedEventHandler
<CoreWindow
^, CoreWindowEventArgs
^>(this, &MyApplicationView::OnWindowClosed
);
181 window
->KeyDown
+= ref
new TypedEventHandler
<CoreWindow
^, KeyEventArgs
^>(this, &MyApplicationView::OnKeyDown
);
182 window
->KeyUp
+= ref
new TypedEventHandler
<CoreWindow
^, KeyEventArgs
^>(this, &MyApplicationView::OnKeyUp
);
183 window
->PointerPressed
+= ref
new TypedEventHandler
<CoreWindow
^, PointerEventArgs
^>(this, &MyApplicationView::OnPointerPressed
);
184 window
->PointerMoved
+= ref
new TypedEventHandler
<CoreWindow
^, PointerEventArgs
^>(this, &MyApplicationView::OnPointerMoved
);
188 void MyApplicationView::Load(Platform::String
^ entryPoint
)
190 InitializeApplication(*m_game
);
193 // Called by the system after initialization is complete. This implements the traditional game loop.
194 void MyApplicationView::Run()
198 // ProcessEvents will throw if the process is exiting, allowing us to break out of the loop. This will be
199 // cleaned up when we get proper process lifetime management in a future release.
200 g_window
->Dispatcher
->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent
);
202 m_IsRunning
= UpdateApplication(*m_game
);
206 void MyApplicationView::Uninitialize()
208 Graphics::Terminate();
209 TerminateApplication(*m_game
);
210 Graphics::Shutdown();
213 // Called when the application is activated. For now, there is just one activation kind - Launch.
214 void MyApplicationView::OnActivated(CoreApplicationView
^ applicationView
, IActivatedEventArgs
^ args
)
216 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
217 float DpiScale
= 96.0f
/ Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->LogicalDpi
;
218 ApplicationView::PreferredLaunchWindowingMode
= ApplicationViewWindowingMode::PreferredLaunchViewSize
;
219 Windows::Foundation::Size
DesiredSize(Graphics::g_DisplayWidth
* DpiScale
, Graphics::g_DisplayHeight
* DpiScale
);
220 ApplicationView::PreferredLaunchViewSize
= DesiredSize
;
221 ApplicationView::GetForCurrentView()->TryResizeView(DesiredSize
);
225 m_IsCapturingPointer
= false;
226 g_window
->Activate();
229 void MyApplicationView::OnSuspending(Platform::Object
^ sender
, SuspendingEventArgs
^ args
) {}
230 void MyApplicationView::OnResuming(Platform::Object
^ sender
, Platform::Object
^ args
) {}
232 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
233 void MyApplicationView::OnWindowSizeChanged(CoreWindow
^ sender
, WindowSizeChangedEventArgs
^ args
)
235 Graphics::Resize((uint32_t)sender
->Bounds
.Width
, (uint32_t)sender
->Bounds
.Height
);
238 void MyApplicationView::OnWindowClosed(CoreWindow
^ sender
, CoreWindowEventArgs
^ args
)
243 void MyApplicationView::OnVisibilityChanged(CoreWindow
^ sender
, VisibilityChangedEventArgs
^ args
) {}
245 void MyApplicationView::OnPointerPressed(CoreWindow
^ sender
, PointerEventArgs
^ args
)
247 //DEBUGPRINT("Pointer pressed (%f, %f)", args->CurrentPoint->RawPosition.X, args->CurrentPoint->RawPosition.Y);
248 if (m_IsCapturingPointer
)
250 g_window
->ReleasePointerCapture();
251 m_IsCapturingPointer
= false;
252 g_window
->PointerCursor
= ref
new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Arrow
, 0);
253 //DEBUGPRINT("Pointer released");
257 g_window
->SetPointerCapture();
258 m_IsCapturingPointer
= true;
259 g_window
->PointerCursor
= ref
new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Hand
, 0);
260 m_PointerX
= args
->CurrentPoint
->RawPosition
.X
;
261 m_PointerY
= args
->CurrentPoint
->RawPosition
.Y
;
262 //DEBUGPRINT("Pointer captured");
266 void MyApplicationView::OnPointerMoved(CoreWindow
^ sender
, PointerEventArgs
^ args
)
268 if (!m_IsCapturingPointer
)
271 float OldX
= m_PointerX
;
272 float OldY
= m_PointerY
;
274 m_PointerX
= args
->CurrentPoint
->RawPosition
.X
;
275 m_PointerY
= args
->CurrentPoint
->RawPosition
.Y
;
277 //DEBUGPRINT("Pointer moved (%f, %f)", m_PointerX, m_PointerY);
278 //DEBUGPRINT("Pointer was (%f, %f)", OldX, OldY);
279 //GameInput::SetMouseMovement(m_PointerX)
282 void MyApplicationView::OnKeyDown(CoreWindow
^ sender
, KeyEventArgs
^ args
)
284 GameInput::SetKeyState(args
->VirtualKey
, true);
287 void MyApplicationView::OnKeyUp(CoreWindow
^ sender
, KeyEventArgs
^ args
)
289 GameInput::SetKeyState(args
->VirtualKey
, false);
293 void RunApplication(IGameApp
&app
, const char *className
)
297 auto applicationViewSource
= ref
new ApplicationViewSource();
298 CoreApplication::Run(applicationViewSource
);
303 struct port_window
*window
= nullptr;
304 struct port port
= {};
306 static void idle(struct port
*port
, void *user_data
)
308 if (!UpdateApplication(*(IGameApp
*)user_data
))
309 port_window_destroy(window
);
312 void RunApplication(IGameApp
&app
, const char *className
)
314 ASSERT(port_init(&port
, &app
));
315 ASSERT(window
= port_window_create(&port
, className
, g_DisplayWidth
, g_DisplayHeight
, &app
));
316 InitializeApplication(app
);
318 port_set_idle_func(&port
, idle
);
319 port_process_events(&port
);
321 Graphics::Terminate();
322 TerminateApplication(app
);
323 Graphics::Shutdown();