First
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "EABase/eabase.h"
|
||||
#if (defined(EA_PLATFORM_MICROSOFT) && !defined(CS_UNDEFINED_STRING) && !EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_DESKTOP))
|
||||
#include <EAAssert/eaassert.h>
|
||||
#include <EAMain/EAMain.h>
|
||||
#include <EAStdC/EASprintf.h>
|
||||
#include <EAStdC/EAString.h>
|
||||
|
||||
EA_DISABLE_ALL_VC_WARNINGS()
|
||||
#pragma warning(disable: 4472 4355) // additional warnings generated by XDK with VS2015
|
||||
#include <memory>
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
|
||||
#if defined EA_PLATFORM_CAPILANO
|
||||
#if defined EAMAIN_CAPILANO_DX12
|
||||
#include <d3d12_x.h>
|
||||
#else
|
||||
#include <d3d11_x.h>
|
||||
#endif
|
||||
#endif
|
||||
EA_RESTORE_ALL_VC_WARNINGS()
|
||||
|
||||
namespace EA
|
||||
{
|
||||
namespace EAMain
|
||||
{
|
||||
|
||||
// Application - implements the required functionality for a application
|
||||
ref class ApplicationView sealed : public Windows::ApplicationModel::Core::IFrameworkView
|
||||
{
|
||||
public:
|
||||
// IFrameworkView Methods
|
||||
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
|
||||
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window) {}
|
||||
virtual void Load(Platform::String^ entryPoint);
|
||||
virtual void Run();
|
||||
virtual void Uninitialize();
|
||||
private:
|
||||
char *mCommandLine;
|
||||
#if EA_PLATFORM_CAPILANO
|
||||
#if defined EAMAIN_CAPILANO_DX12
|
||||
ID3D12CommandQueue* mpCommandQueue;
|
||||
#else
|
||||
ID3DXboxPerformanceContext* mpD3DXboxPerfContext;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void CreateDeviceResources();
|
||||
void OnActivated( Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args );
|
||||
};
|
||||
|
||||
// ApplicationSource - responsible for creating the Application instance and passing it back to the system
|
||||
ref class ApplicationViewSource : Windows::ApplicationModel::Core::IFrameworkViewSource
|
||||
{
|
||||
public:
|
||||
virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
|
||||
{
|
||||
return ref new ApplicationView();
|
||||
}
|
||||
};
|
||||
|
||||
void OutputAppTransition(const char* transition, const wchar_t* sender, const wchar_t* args)
|
||||
{
|
||||
char msg[1024];
|
||||
|
||||
EA::StdC::Snprintf(msg, EAArrayCount(msg), "****\n app is %s.\n sender: ", transition);
|
||||
EA::StdC::Strlcat(msg, sender, EAArrayCount(msg));
|
||||
EA::StdC::Strlcat(msg, "\n args: ", EAArrayCount(msg));
|
||||
EA::StdC::Strlcat(msg, args, EAArrayCount(msg));
|
||||
EA::StdC::Strlcat(msg, "\n****\n", EAArrayCount(msg));
|
||||
|
||||
OutputDebugStringA(msg);
|
||||
}
|
||||
|
||||
void ApplicationView::CreateDeviceResources()
|
||||
{
|
||||
#if defined EA_PLATFORM_CAPILANO
|
||||
#if defined EAMAIN_CAPILANO_DX12
|
||||
ID3D12Device* pD3DDevice;
|
||||
|
||||
HRESULT hr = D3D12CreateDevice(
|
||||
nullptr, // specify null to use the default adapter
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
__uuidof(ID3D12Device),
|
||||
(void**)&pD3DDevice
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
OutputDebugStringA("Failed to create device. Suspending will not work for this application.");
|
||||
return;
|
||||
}
|
||||
|
||||
D3D12XBOX_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.EngineOrPipeIndex = 0;
|
||||
queueDesc.QueueIndex = 0;
|
||||
|
||||
hr = pD3DDevice->CreateCommandQueueX(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&mpCommandQueue);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
OutputDebugStringA("Failed to create command queue. Suspending will not work for this application.");
|
||||
}
|
||||
|
||||
if (pD3DDevice) { pD3DDevice->Release(); pD3DDevice = NULL; }
|
||||
#else
|
||||
// This flag adds support for surfaces with a different color channel ordering than the API default.
|
||||
// It is recommended usage, and is required for compatibility with Direct2D.
|
||||
UINT creationFlags = D3D11_CREATE_DEVICE_INSTRUMENTED;
|
||||
|
||||
// This array defines the set of DirectX hardware feature levels this app will support.
|
||||
// Note the ordering should be preserved.
|
||||
// Don't forget to declare your application's minimum required feature level in its
|
||||
// description. All applications are assumed to support 9.1 unless otherwise stated.
|
||||
D3D_FEATURE_LEVEL featureLevels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_0
|
||||
};
|
||||
|
||||
// Create the DX11 API device object, and get a corresponding context.
|
||||
ID3D11Device* pD3DDevice;
|
||||
ID3D11DeviceContext* pD3DDeviceContext;
|
||||
|
||||
HRESULT hr = D3D11CreateDevice(
|
||||
nullptr, // specify null to use the default adapter
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
nullptr, // leave as nullptr unless software device
|
||||
creationFlags, // optionally set debug and Direct2D compatibility flags
|
||||
featureLevels, // list of feature levels this app can support
|
||||
ARRAYSIZE(featureLevels), // number of entries in above list
|
||||
D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION
|
||||
&pD3DDevice, // returns the Direct3D device created
|
||||
NULL, // returns feature level of device created
|
||||
&pD3DDeviceContext // returns the device immediate context
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
OutputDebugStringA("Failed to create device. Suspending will not work for this application.");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = pD3DDevice->QueryInterface(__uuidof(mpD3DXboxPerfContext), (void **)&mpD3DXboxPerfContext);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
OutputDebugStringA("Failed to get perfcontext. Suspending will not work for this application.");
|
||||
}
|
||||
|
||||
if (pD3DDevice) { pD3DDevice->Release(); pD3DDevice = NULL; }
|
||||
if (pD3DDeviceContext) { pD3DDeviceContext->Release(); pD3DDeviceContext = NULL; }
|
||||
#endif
|
||||
#else
|
||||
// Do nothing
|
||||
#endif
|
||||
}
|
||||
|
||||
// Called by the system. Perform application initialization here,
|
||||
// hooking application wide events, etc.
|
||||
void ApplicationView::Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView)
|
||||
{
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::ApplicationModel;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::ApplicationModel::Activation;
|
||||
|
||||
// Creates any resources required by the platform to run an application / enable a particular feature set (like GPU profiling or suspend/resume)
|
||||
CreateDeviceResources();
|
||||
|
||||
#pragma warning(push)
|
||||
// Disables warning for MS class 'Windows::Foundation::TypedEventHandler<TSender,TResult>::{ctor}::__abi_PointerToMemberCapture'
|
||||
// "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'"
|
||||
#pragma warning(disable:4371)
|
||||
applicationView->Activated += ref new Windows::Foundation::TypedEventHandler< CoreApplicationView^, IActivatedEventArgs^ >( this, &ApplicationView::OnActivated );
|
||||
#pragma warning(pop)
|
||||
CoreApplication::Suspending += ref new EventHandler<SuspendingEventArgs^>([this](Object^ sender, SuspendingEventArgs^ args) {
|
||||
OutputAppTransition("suspending", sender ? sender->ToString()->Data() : L"NULL", args ? args->ToString()->Data() : L"NULL");
|
||||
#if defined EA_PLATFORM_CAPILANO
|
||||
#if defined EAMAIN_CAPILANO_DX12
|
||||
mpCommandQueue->SuspendX(0);
|
||||
#else
|
||||
mpD3DXboxPerfContext->Suspend(0);
|
||||
#endif
|
||||
#endif
|
||||
});
|
||||
CoreApplication::Resuming += ref new EventHandler<Object^>([this](Object^ sender, Object^ args) {
|
||||
OutputAppTransition("resuming", sender ? sender->ToString()->Data() : L"NULL", args ? args->ToString()->Data() : L"NULL");
|
||||
#if defined EA_PLATFORM_CAPILANO
|
||||
#if defined EAMAIN_CAPILANO_DX12
|
||||
mpCommandQueue->ResumeX();
|
||||
#else
|
||||
mpD3DXboxPerfContext->Resume();
|
||||
#endif
|
||||
#endif
|
||||
});
|
||||
CoreApplication::Exiting += ref new EventHandler<Object^>([](Object^ sender, Object^ args) {
|
||||
OutputAppTransition("exiting", sender ? sender->ToString()->Data() : L"NULL", args ? args->ToString()->Data() : L"NULL");
|
||||
});
|
||||
}
|
||||
|
||||
static char *ConvertLaunchArgsToMultibyte(LPCWSTR rawArgumentString, int rawArgumentStringLength)
|
||||
{
|
||||
int bufferSize = WideCharToMultiByte(
|
||||
CP_UTF8,
|
||||
0,
|
||||
rawArgumentString,
|
||||
rawArgumentStringLength,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
char *commandLine = static_cast<char *>(calloc(bufferSize + 1, 1));
|
||||
int rv = WideCharToMultiByte(
|
||||
CP_UTF8,
|
||||
0,
|
||||
rawArgumentString,
|
||||
rawArgumentStringLength,
|
||||
commandLine,
|
||||
bufferSize + 1,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
commandLine[bufferSize] = 0;
|
||||
EA_ASSERT(rv == bufferSize);
|
||||
EA_UNUSED(rv); // avoids warnings in opt builds regarding unused variables
|
||||
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
static char *ReadArgsFromFile()
|
||||
{
|
||||
FILE *fp = fopen("EAMainArgsFile.txt", "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
size_t fileSize;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
fileSize = static_cast<size_t>(ftell(fp));
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
char *argsBuffer = static_cast<char *>(calloc(fileSize + 1, 1));
|
||||
|
||||
if (fread(argsBuffer, 1, fileSize, fp) != fileSize)
|
||||
{
|
||||
goto error_return_free_buffer;
|
||||
}
|
||||
|
||||
return argsBuffer;
|
||||
|
||||
error_return_free_buffer:
|
||||
free(argsBuffer);
|
||||
fclose(fp);
|
||||
|
||||
error_return:
|
||||
return static_cast<char *>(calloc(1, 1));
|
||||
}
|
||||
|
||||
void ApplicationView::OnActivated( Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args )
|
||||
{
|
||||
if (args->Kind == Windows::ApplicationModel::Activation::ActivationKind::Launch)
|
||||
{
|
||||
Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^launchArgs = (Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^) args;
|
||||
Platform::String ^argumentString = launchArgs->Arguments;
|
||||
LPCWSTR rawArgumentString = argumentString->Data();
|
||||
int rawArgumentStringLength = argumentString->Length();
|
||||
|
||||
if (rawArgumentString == NULL || wcslen(rawArgumentString) == 0)
|
||||
{
|
||||
mCommandLine = ReadArgsFromFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCommandLine = ConvertLaunchArgsToMultibyte(rawArgumentString, rawArgumentStringLength);
|
||||
}
|
||||
}
|
||||
Windows::UI::Core::CoreWindow::GetForCurrentThread()->Activate();
|
||||
}
|
||||
|
||||
void ApplicationView::Load(Platform::String^ entryPoint)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Called by the system after initialization is complete. This implements the traditional game loop.
|
||||
void ApplicationView::Run()
|
||||
{
|
||||
using namespace EA::EAMain;
|
||||
std::unique_ptr<IWinRTRunner> winRTRunner(CreateWinRTRunner());
|
||||
|
||||
CommandLine commandline(mCommandLine, CommandLine::FLAG_NO_PROGRAM_NAME);
|
||||
|
||||
winRTRunner->Run(commandline.Argc(),commandline.Argv());
|
||||
do
|
||||
{
|
||||
// ProcessEvents will throw if the process is exiting, allowing us to
|
||||
// break out of the loop. This will be cleaned up when we get proper
|
||||
// process lifetime management online in a future release.
|
||||
Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
} while(!winRTRunner->IsFinished());
|
||||
|
||||
winRTRunner->ReportResult();
|
||||
Windows::ApplicationModel::Core::CoreApplication::Exit();
|
||||
|
||||
free(mCommandLine);
|
||||
mCommandLine = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void ApplicationView::Uninitialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
EAMAIN_API void StartWinRtApplication()
|
||||
{
|
||||
// To do: store args so they can be passed to EAEntryPointMain.
|
||||
Windows::ApplicationModel::Core::CoreApplication::Run(ref new ApplicationViewSource());
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace EAMain
|
||||
} // namespace EA
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user