EAEntryPointMain.cpp 12 KB

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