EAEntryPointMain.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #include "EABase/eabase.h"
  2. #if (defined(EA_PLATFORM_MICROSOFT) && !defined(CS_UNDEFINED_STRING) && !EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP))
  3. #include <EAAssert/eaassert.h>
  4. #include <EAMain/EAMain.h>
  5. #include <EAStdC/EASprintf.h>
  6. #include <EAStdC/EAString.h>
  7. EA_DISABLE_ALL_VC_WARNINGS()
  8. #pragma warning(disable: 4472 4355) // additional warnings generated by XDK with VS2015
  9. #include <memory>
  10. #ifndef WIN32_LEAN_AND_MEAN
  11. #define WIN32_LEAN_AND_MEAN
  12. #endif
  13. #include <Windows.h>
  14. #if defined EA_PLATFORM_CAPILANO
  15. #if defined EAMAIN_CAPILANO_DX12
  16. #include <d3d12_x.h>
  17. #else
  18. #include <d3d11_x.h>
  19. #endif
  20. #endif
  21. EA_RESTORE_ALL_VC_WARNINGS()
  22. namespace EA
  23. {
  24. namespace EAMain
  25. {
  26. // Application - implements the required functionality for a application
  27. ref class ApplicationView sealed : public Windows::ApplicationModel::Core::IFrameworkView
  28. {
  29. public:
  30. // IFrameworkView Methods
  31. virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
  32. virtual void SetWindow(Windows::UI::Core::CoreWindow^ window) {}
  33. virtual void Load(Platform::String^ entryPoint);
  34. virtual void Run();
  35. virtual void Uninitialize();
  36. private:
  37. char *mCommandLine;
  38. #if EA_PLATFORM_CAPILANO
  39. #if defined EAMAIN_CAPILANO_DX12
  40. ID3D12CommandQueue* mpCommandQueue;
  41. #else
  42. ID3DXboxPerformanceContext* mpD3DXboxPerfContext;
  43. #endif
  44. #endif
  45. void CreateDeviceResources();
  46. void OnActivated( Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args );
  47. };
  48. // ApplicationSource - responsible for creating the Application instance and passing it back to the system
  49. ref class ApplicationViewSource : Windows::ApplicationModel::Core::IFrameworkViewSource
  50. {
  51. public:
  52. virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
  53. {
  54. return ref new ApplicationView();
  55. }
  56. };
  57. void OutputAppTransition(const char* transition, const wchar_t* sender, const wchar_t* args)
  58. {
  59. char msg[1024];
  60. EA::StdC::Snprintf(msg, EAArrayCount(msg), "****\n app is %s.\n sender: ", transition);
  61. EA::StdC::Strlcat(msg, sender, EAArrayCount(msg));
  62. EA::StdC::Strlcat(msg, "\n args: ", EAArrayCount(msg));
  63. EA::StdC::Strlcat(msg, args, EAArrayCount(msg));
  64. EA::StdC::Strlcat(msg, "\n****\n", EAArrayCount(msg));
  65. OutputDebugStringA(msg);
  66. }
  67. void ApplicationView::CreateDeviceResources()
  68. {
  69. #if defined EA_PLATFORM_CAPILANO
  70. #if defined EAMAIN_CAPILANO_DX12
  71. ID3D12Device* pD3DDevice;
  72. HRESULT hr = D3D12CreateDevice(
  73. nullptr, // specify null to use the default adapter
  74. D3D_FEATURE_LEVEL_11_0,
  75. __uuidof(ID3D12Device),
  76. (void**)&pD3DDevice
  77. );
  78. if (FAILED(hr))
  79. {
  80. OutputDebugStringA("Failed to create device. Suspending will not work for this application.");
  81. return;
  82. }
  83. D3D12XBOX_COMMAND_QUEUE_DESC queueDesc = {};
  84. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
  85. queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
  86. queueDesc.EngineOrPipeIndex = 0;
  87. queueDesc.QueueIndex = 0;
  88. hr = pD3DDevice->CreateCommandQueueX(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&mpCommandQueue);
  89. if (FAILED(hr))
  90. {
  91. OutputDebugStringA("Failed to create command queue. Suspending will not work for this application.");
  92. }
  93. if (pD3DDevice) { pD3DDevice->Release(); pD3DDevice = NULL; }
  94. #else
  95. // This flag adds support for surfaces with a different color channel ordering than the API default.
  96. // It is recommended usage, and is required for compatibility with Direct2D.
  97. UINT creationFlags = D3D11_CREATE_DEVICE_INSTRUMENTED;
  98. // This array defines the set of DirectX hardware feature levels this app will support.
  99. // Note the ordering should be preserved.
  100. // Don't forget to declare your application's minimum required feature level in its
  101. // description. All applications are assumed to support 9.1 unless otherwise stated.
  102. D3D_FEATURE_LEVEL featureLevels[] =
  103. {
  104. D3D_FEATURE_LEVEL_11_0
  105. };
  106. // Create the DX11 API device object, and get a corresponding context.
  107. ID3D11Device* pD3DDevice;
  108. ID3D11DeviceContext* pD3DDeviceContext;
  109. HRESULT hr = D3D11CreateDevice(
  110. nullptr, // specify null to use the default adapter
  111. D3D_DRIVER_TYPE_HARDWARE,
  112. nullptr, // leave as nullptr unless software device
  113. creationFlags, // optionally set debug and Direct2D compatibility flags
  114. featureLevels, // list of feature levels this app can support
  115. ARRAYSIZE(featureLevels), // number of entries in above list
  116. D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION
  117. &pD3DDevice, // returns the Direct3D device created
  118. NULL, // returns feature level of device created
  119. &pD3DDeviceContext // returns the device immediate context
  120. );
  121. if (FAILED(hr))
  122. {
  123. OutputDebugStringA("Failed to create device. Suspending will not work for this application.");
  124. return;
  125. }
  126. hr = pD3DDevice->QueryInterface(__uuidof(mpD3DXboxPerfContext), (void **)&mpD3DXboxPerfContext);
  127. if (FAILED(hr))
  128. {
  129. OutputDebugStringA("Failed to get perfcontext. Suspending will not work for this application.");
  130. }
  131. if (pD3DDevice) { pD3DDevice->Release(); pD3DDevice = NULL; }
  132. if (pD3DDeviceContext) { pD3DDeviceContext->Release(); pD3DDeviceContext = NULL; }
  133. #endif
  134. #else
  135. // Do nothing
  136. #endif
  137. }
  138. // Called by the system. Perform application initialization here,
  139. // hooking application wide events, etc.
  140. void ApplicationView::Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView)
  141. {
  142. using namespace Platform;
  143. using namespace Windows::Foundation;
  144. using namespace Windows::ApplicationModel;
  145. using namespace Windows::ApplicationModel::Core;
  146. using namespace Windows::ApplicationModel::Activation;
  147. // Creates any resources required by the platform to run an application / enable a particular feature set (like GPU profiling or suspend/resume)
  148. CreateDeviceResources();
  149. #pragma warning(push)
  150. // Disables warning for MS class 'Windows::Foundation::TypedEventHandler<TSender,TResult>::{ctor}::__abi_PointerToMemberCapture'
  151. // "layout of class may have changed from a previous version of the compiler due to better packing of member 'Windows::Foundation::TypedEventHandler<TSender,TResult>::{ctor}::__abi_PointerToMemberCapture::member'"
  152. #pragma warning(disable:4371)
  153. applicationView->Activated += ref new Windows::Foundation::TypedEventHandler< CoreApplicationView^, IActivatedEventArgs^ >( this, &ApplicationView::OnActivated );
  154. #pragma warning(pop)
  155. CoreApplication::Suspending += ref new EventHandler<SuspendingEventArgs^>([this](Object^ sender, SuspendingEventArgs^ args) {
  156. OutputAppTransition("suspending", sender ? sender->ToString()->Data() : L"NULL", args ? args->ToString()->Data() : L"NULL");
  157. #if defined EA_PLATFORM_CAPILANO
  158. #if defined EAMAIN_CAPILANO_DX12
  159. mpCommandQueue->SuspendX(0);
  160. #else
  161. mpD3DXboxPerfContext->Suspend(0);
  162. #endif
  163. #endif
  164. });
  165. CoreApplication::Resuming += ref new EventHandler<Object^>([this](Object^ sender, Object^ args) {
  166. OutputAppTransition("resuming", sender ? sender->ToString()->Data() : L"NULL", args ? args->ToString()->Data() : L"NULL");
  167. #if defined EA_PLATFORM_CAPILANO
  168. #if defined EAMAIN_CAPILANO_DX12
  169. mpCommandQueue->ResumeX();
  170. #else
  171. mpD3DXboxPerfContext->Resume();
  172. #endif
  173. #endif
  174. });
  175. CoreApplication::Exiting += ref new EventHandler<Object^>([](Object^ sender, Object^ args) {
  176. OutputAppTransition("exiting", sender ? sender->ToString()->Data() : L"NULL", args ? args->ToString()->Data() : L"NULL");
  177. });
  178. }
  179. static char *ConvertLaunchArgsToMultibyte(LPCWSTR rawArgumentString, int rawArgumentStringLength)
  180. {
  181. int bufferSize = WideCharToMultiByte(
  182. CP_UTF8,
  183. 0,
  184. rawArgumentString,
  185. rawArgumentStringLength,
  186. NULL,
  187. 0,
  188. NULL,
  189. NULL);
  190. char *commandLine = static_cast<char *>(calloc(bufferSize + 1, 1));
  191. int rv = WideCharToMultiByte(
  192. CP_UTF8,
  193. 0,
  194. rawArgumentString,
  195. rawArgumentStringLength,
  196. commandLine,
  197. bufferSize + 1,
  198. NULL,
  199. NULL);
  200. commandLine[bufferSize] = 0;
  201. EA_ASSERT(rv == bufferSize);
  202. EA_UNUSED(rv); // avoids warnings in opt builds regarding unused variables
  203. return commandLine;
  204. }
  205. static char *ReadArgsFromFile()
  206. {
  207. FILE *fp = fopen("EAMainArgsFile.txt", "rb");
  208. if (fp == NULL)
  209. {
  210. goto error_return;
  211. }
  212. size_t fileSize;
  213. fseek(fp, 0, SEEK_END);
  214. fileSize = static_cast<size_t>(ftell(fp));
  215. fseek(fp, 0, SEEK_SET);
  216. char *argsBuffer = static_cast<char *>(calloc(fileSize + 1, 1));
  217. if (fread(argsBuffer, 1, fileSize, fp) != fileSize)
  218. {
  219. goto error_return_free_buffer;
  220. }
  221. return argsBuffer;
  222. error_return_free_buffer:
  223. free(argsBuffer);
  224. fclose(fp);
  225. error_return:
  226. return static_cast<char *>(calloc(1, 1));
  227. }
  228. void ApplicationView::OnActivated( Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args )
  229. {
  230. if (args->Kind == Windows::ApplicationModel::Activation::ActivationKind::Launch)
  231. {
  232. Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^launchArgs = (Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^) args;
  233. Platform::String ^argumentString = launchArgs->Arguments;
  234. LPCWSTR rawArgumentString = argumentString->Data();
  235. int rawArgumentStringLength = argumentString->Length();
  236. if (rawArgumentString == NULL || wcslen(rawArgumentString) == 0)
  237. {
  238. mCommandLine = ReadArgsFromFile();
  239. }
  240. else
  241. {
  242. mCommandLine = ConvertLaunchArgsToMultibyte(rawArgumentString, rawArgumentStringLength);
  243. }
  244. }
  245. Windows::UI::Core::CoreWindow::GetForCurrentThread()->Activate();
  246. }
  247. void ApplicationView::Load(Platform::String^ entryPoint)
  248. {
  249. }
  250. // Called by the system after initialization is complete. This implements the traditional game loop.
  251. void ApplicationView::Run()
  252. {
  253. using namespace EA::EAMain;
  254. std::unique_ptr<IWinRTRunner> winRTRunner(CreateWinRTRunner());
  255. CommandLine commandline(mCommandLine, CommandLine::FLAG_NO_PROGRAM_NAME);
  256. winRTRunner->Run(commandline.Argc(),commandline.Argv());
  257. do
  258. {
  259. // ProcessEvents will throw if the process is exiting, allowing us to
  260. // break out of the loop. This will be cleaned up when we get proper
  261. // process lifetime management online in a future release.
  262. Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
  263. } while(!winRTRunner->IsFinished());
  264. winRTRunner->ReportResult();
  265. Windows::ApplicationModel::Core::CoreApplication::Exit();
  266. free(mCommandLine);
  267. mCommandLine = nullptr;
  268. }
  269. void ApplicationView::Uninitialize()
  270. {
  271. }
  272. namespace Internal
  273. {
  274. EAMAIN_API void StartWinRtApplication()
  275. {
  276. // To do: store args so they can be passed to EAEntryPointMain.
  277. Windows::ApplicationModel::Core::CoreApplication::Run(ref new ApplicationViewSource());
  278. }
  279. } // namespace Internal
  280. } // namespace EAMain
  281. } // namespace EA
  282. #endif