JD2022-TU1/main/extern/UbiServices/custom/tests/xone/testMainXone.cpp

390 lines
14 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour //
////////////////////////////////////////////////////////////////////////////////
#include "tests/config.h"
#include <xdk.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <windows.h>
//#define US_ENABLE_XB1_UI
#if defined(US_ENABLE_XB1_UI)
#include <d3d11_x.h>
#endif
#include <../private/ubiservices/core/debug/assert.h>
#include "ubiservices/core/log/log.h"
#include <agile.h>
int mainXboxOne(int argc, US_NS::tchar** argv); // Forward declaration
// Application - implements the required functionality for a application
ref class ApplicationView sealed : public Windows::ApplicationModel::Core::IFrameworkView
{
Platform::String^ m_arguments;
// http://stackoverflow.com/questions/236129/splitting-a-string-in-c
static std::vector<std::wstring>& split(const std::wstring& s, US_NS::wchar delim, std::vector<std::wstring>& elems)
{
std::wstringstream ss(s);
std::wstring item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
// http://stackoverflow.com/questions/236129/splitting-a-string-in-c
static std::vector<std::wstring> split(const std::wstring& s, US_NS::wchar delim)
{
std::vector<std::wstring> elems;
split(s, delim, elems);
return elems;
}
static DWORD __stdcall objectThreadProc(void* param)
{
ApplicationView^ thisInstance = reinterpret_cast<ApplicationView^>(param);
Platform::String^ argumentsExt = "DummyExecutableName " + thisInstance->m_arguments;
std::vector<std::wstring> argumentsV = split(std::wstring(argumentsExt->Data()), _T(' '));
bool gettingOutputlog = false;
US_NS::tchar* arguments[20];
for (US_NS::uint32 index = 0; index < argumentsV.size() && index < sizeof(arguments)/sizeof(arguments[0]) && !gettingOutputlog; index++)
{
gettingOutputlog = (argumentsV[index] == L"GETLOGS");
arguments[index] = const_cast<US_NS::tchar*>(argumentsV[index].c_str());
}
mainXboxOne(gettingOutputlog ? 0 : static_cast<int>(argumentsV.size()), arguments);
m_done = true;
return 0;
}
#if defined(US_ENABLE_XB1_UI)
Microsoft::WRL::ComPtr<ID3D11DeviceX> m_d3dDevice;
Microsoft::WRL::ComPtr<ID3D11DeviceContextX> m_d3dContext;
//Platform::Agile<Windows::UI::Core::CoreWindow> m_window;
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
// Set a breakpoint on this line to catch DirectX API errors
throw Platform::Exception::CreateException(hr);
}
}
void CreateDevice()
{
assert(!(m_window == nullptr));
// Create the DX11 API device object, and get a corresponding context.
Microsoft::WRL::ComPtr<ID3D11DeviceX> device;
Microsoft::WRL::ComPtr<ID3D11DeviceContextX> context;
D3D11X_CREATE_DEVICE_PARAMETERS params;
ZeroMemory(&params, sizeof(D3D11X_CREATE_DEVICE_PARAMETERS));
params.Flags = D3D11_CREATE_DEVICE_DEBUG;
params.Version = D3D11_SDK_VERSION;
ThrowIfFailed(D3D11XCreateDeviceX(&params, &device, &context)); // d3d11_x.lib
// Get the DirectX11.1 device by QI off the DirectX11 one.
ThrowIfFailed(device.As(&m_d3dDevice));
// And get the corresponding device context in the same way.
ThrowIfFailed(context.As(&m_d3dContext));
// First, retrieve the underlying DXGI Device from the D3D Device
Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice;
ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
// Identify the physical adapter (GPU or card) this device is running on.
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
ThrowIfFailed(dxgiDevice->GetAdapter(&dxgiAdapter));
// And obtain the factory object that created it.
Microsoft::WRL::ComPtr<IDXGIFactory2> dxgiFactory;
ThrowIfFailed(dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), &dxgiFactory));
// Create a descriptor for the swap chain.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = 1920;
swapChainDesc.Height = 1080;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2;
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Flags = 0;
// Create a SwapChain from a CoreWindow.
ThrowIfFailed(dxgiFactory->CreateSwapChainForCoreWindow(
m_d3dDevice.Get(), reinterpret_cast<IUnknown*>(m_window.Get()), &swapChainDesc, nullptr, &m_swapChain));
}
#endif
public:
ApplicationView()
: m_thread(NULL)
{
m_done = false;
}
// IFrameworkView Methods
// Called by the system. Perform application initialization here, hooking application wide events, etc.
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView)
{
using Windows::ApplicationModel::Activation::IActivatedEventArgs;
using Windows::ApplicationModel::Core::CoreApplicationView;
using Windows::Foundation::TypedEventHandler;
applicationView->Activated +=
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &ApplicationView::OnViewActivated);
// The following event handlers are not required for tests except that
// it demonstrates that the main program can subscribe to events while
// the SDK do the same showing that both receives the same events...
#define US_ENABLE_MAIN_EVENS_LOGS
#if defined(US_ENABLE_MAIN_EVENS_LOGS)
Windows::ApplicationModel::Core::CoreApplication::ResourceAvailabilityChanged +=
ref new Windows::Foundation::EventHandler<Platform::Object^>(this, &ApplicationView::OnResourceAvailabilityChanged);
Windows::ApplicationModel::Core::CoreApplication::Suspending +=
ref new Windows::Foundation::EventHandler<Windows::ApplicationModel::SuspendingEventArgs^>(this, &ApplicationView::OnSuspending);
Windows::ApplicationModel::Core::CoreApplication::Resuming +=
ref new Windows::Foundation::EventHandler<Platform::Object^>(this, &ApplicationView::OnResuming);
#endif
}
// Called when we are provided a window.
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window)
{
m_window = window;
#if defined(US_ENABLE_XB1_UI)
CreateDevice();
#endif
window->Activate(); // Calling it or not does not make any difference.
}
virtual void Load(Platform::String^ entryPoint)
{
//m_game = ref new Game();
//m_game->Initialize(CoreWindow::GetForCurrentThread());
}
// Called by the system after initialization is complete. This implements the traditional game loop
virtual void Run()
{
for (; !m_done;)
{
// 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);
//m_game->Tick();
#if defined(US_ENABLE_XB1_UI)
m_swapChain->Present(1, 0);
#endif
}
m_window->Close();
//Windows::ApplicationModel::Core::CoreApplication::Exit(); // Not required anymore?
}
#if defined(US_ENABLE_XB1_UI) // Code is missing for attaching these handlers to the event sources...
virtual void Suspend(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args)
{
m_d3dContext->Suspend(0);
}
virtual void Resume(Platform::Object^ sender, Platform::Object^ args)
{
m_d3dContext->Resume();
}
#endif
virtual void Uninitialize()
{
US_VERIFY(CloseHandle(m_thread) != FALSE); // Calling it or not does not make any difference.
// Exiting explicitly here avoid the appmodel.dll thread to raise an
// unhandled exception (access violation reading...).
exit(0);
}
protected:
// Event Handlers
// Called when the application is activated. For now, there is just one activation kind - Launch.
void OnViewActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args)
{
if (args->Kind == Windows::ApplicationModel::Activation::ActivationKind::Launch)
{
#if defined(US_ENABLE_MAIN_EVENS_LOGS)
using Windows::Foundation::TypedEventHandler;
US_ASSERT(Windows::UI::Core::CoreWindow::GetForCurrentThread() == applicationView->CoreWindow, "Information");
applicationView->CoreWindow->Activated +=
ref new TypedEventHandler<Windows::UI::Core::CoreWindow^, Windows::UI::Core::WindowActivatedEventArgs^>(this, &ApplicationView::OnActivated);
applicationView->CoreWindow->VisibilityChanged +=
ref new TypedEventHandler<Windows::UI::Core::CoreWindow^, Windows::UI::Core::VisibilityChangedEventArgs^>(this, &ApplicationView::OnVisibilityChanged);
US_NS::Log::print("[ MAIN!!!! ] ApplicationView OnViewActivated where Kind is Launch\n");
#endif
auto launchArgs = (Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^)args;
m_arguments = launchArgs->Arguments;
}
#if defined(US_ENABLE_MAIN_EVENS_LOGS)
else
{
US_NS::Log::print("[ MAIN!!!! ] ApplicationView OnViewActivated where Kind is %d\n", args->Kind);
}
#endif
Windows::UI::Core::CoreWindow::GetForCurrentThread()->Activate();
m_thread = reinterpret_cast<HANDLE>(CreateThread(NULL,
(64*1024), //ObjectThreadRootPlatform::s_threadStackSize,
reinterpret_cast<LPTHREAD_START_ROUTINE>(objectThreadProc),
reinterpret_cast<LPVOID>(this),
0,
reinterpret_cast<unsigned long*>(&m_threadId)));
}
#if defined(US_ENABLE_MAIN_EVENS_LOGS)
void OnActivated(Windows::UI::Core::CoreWindow^ applicationView, Windows::UI::Core::WindowActivatedEventArgs^ args)
{
static bool once = false;
switch (args->WindowActivationState)
{
case Windows::UI::Core::CoreWindowActivationState::CodeActivated:
case Windows::UI::Core::CoreWindowActivationState::PointerActivated:
US_NS::Log::print("[ MAIN!!!! ] OnActivated where WindowActivationState is CodeActivated/PointerActivated\n");
if (once)
{
//US_NS::PlatformHelper::changeState(US_NS::PlatformHelper::Foreground);
}
break;
case Windows::UI::Core::CoreWindowActivationState::Deactivated:
US_NS::Log::print("[ MAIN!!!! ] OnActivated where WindowActivationState is Deactivated\n");
if (once)
{
//US_NS::PlatformHelper::changeState(US_NS::PlatformHelper::Background);
}
break;
default:
US_ASSERT(false, "Invalid enumeration value");
break;
}
once = true;
}
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ applicationView, Windows::UI::Core::VisibilityChangedEventArgs^ args)
{
static bool once = false;
US_NS::Log::print("[ MAIN!!!! ] OnVisibilityChanged to %s\n", args->Visible ? "Visible" : "Invisible");
if (once)
{
//US_NS::PlatformHelper::changeState(args->Visible ? US_NS::PlatformHelper::Foreground : US_NS::PlatformHelper::Background);
}
once = true;
}
void OnResourceAvailabilityChanged(Platform::Object^ sender, Platform::Object^ args)
{
US_UNUSED(sender);
US_UNUSED(args);
switch (Windows::ApplicationModel::Core::CoreApplication::ResourceAvailability)
{
case Windows::ApplicationModel::Core::ResourceAvailability::Full:
US_NS::Log::print("[ MAIN!!!! ] ResourceAvailability::Full\n");
break;
case Windows::ApplicationModel::Core::ResourceAvailability::Constrained:
US_NS::Log::print("[ MAIN!!!! ] ResourceAvailability::Constrained\n");
break;
case Windows::ApplicationModel::Core::ResourceAvailability::FullWithExtendedSystemReserve:
US_NS::Log::print("[ MAIN!!!! ] ResourceAvailability::FullWithExtendedSystemReserve\n");
break;
default:
US_ASSERT(false, "Invalid enumeration value");
break;
}
}
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args)
{
//auto test = args->SuspendingOperation->GetDeferral();
US_UNUSED(sender);
US_UNUSED(args);
US_NS::Log::print("[ MAIN!!!! ] OnSuspending!\n");
}
void OnResuming(Platform::Object^ sender, Platform::Object^ args)
{
US_UNUSED(sender);
US_UNUSED(args);
US_NS::Log::print("[ MAIN!!!! ] OnResuming!\n");
}
#endif
private:
friend Windows::UI::Core::CoreWindow^ getCoreWindow();
static Platform::Agile<Windows::UI::Core::CoreWindow> m_window; // (proof of concept)
static bool m_done;
HANDLE m_thread;
unsigned long* m_threadId;
};
Platform::Agile<Windows::UI::Core::CoreWindow> ApplicationView::m_window;
Windows::UI::Core::CoreWindow^ getCoreWindow()
{
return ApplicationView::m_window.Get();
}
// Creates the Application instance and pass it back to the system
ref class ApplicationViewSource : Windows::ApplicationModel::Core::IFrameworkViewSource
{
public:
// Implements an IFrameworkView factory.
virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
{
return ref new ApplicationView();
}
};
bool ApplicationView::m_done;
// Application entry point
//[Platform::MTAThread] // Does not make any difference?
int main(Platform::Array<Platform::String^>^ args)
{
auto applicationViewSource = ref new ApplicationViewSource();
Windows::ApplicationModel::Core::CoreApplication::Run(applicationViewSource);
return 0;
}