//////////////////////////////////////////////////////////////////////////////// // (c) Copyright, Ubisoft Entertainment Inc. || Created by Harbour // //////////////////////////////////////////////////////////////////////////////// #include "tests/config.h" #include #include #include #include #include #include //#define US_ENABLE_XB1_UI #if defined(US_ENABLE_XB1_UI) #include #endif #include <../private/ubiservices/core/debug/assert.h> #include "ubiservices/core/log/log.h" #include 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& split(const std::wstring& s, US_NS::wchar delim, std::vector& 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 split(const std::wstring& s, US_NS::wchar delim) { std::vector elems; split(s, delim, elems); return elems; } static DWORD __stdcall objectThreadProc(void* param) { ApplicationView^ thisInstance = reinterpret_cast(param); Platform::String^ argumentsExt = "DummyExecutableName " + thisInstance->m_arguments; std::vector 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(argumentsV[index].c_str()); } mainXboxOne(gettingOutputlog ? 0 : static_cast(argumentsV.size()), arguments); m_done = true; return 0; } #if defined(US_ENABLE_XB1_UI) Microsoft::WRL::ComPtr m_d3dDevice; Microsoft::WRL::ComPtr m_d3dContext; //Platform::Agile m_window; Microsoft::WRL::ComPtr 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 device; Microsoft::WRL::ComPtr context; D3D11X_CREATE_DEVICE_PARAMETERS params; ZeroMemory(¶ms, sizeof(D3D11X_CREATE_DEVICE_PARAMETERS)); params.Flags = D3D11_CREATE_DEVICE_DEBUG; params.Version = D3D11_SDK_VERSION; ThrowIfFailed(D3D11XCreateDeviceX(¶ms, &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 dxgiDevice; ThrowIfFailed(m_d3dDevice.As(&dxgiDevice)); // Identify the physical adapter (GPU or card) this device is running on. Microsoft::WRL::ComPtr dxgiAdapter; ThrowIfFailed(dxgiDevice->GetAdapter(&dxgiAdapter)); // And obtain the factory object that created it. Microsoft::WRL::ComPtr 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(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(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(this, &ApplicationView::OnResourceAvailabilityChanged); Windows::ApplicationModel::Core::CoreApplication::Suspending += ref new Windows::Foundation::EventHandler(this, &ApplicationView::OnSuspending); Windows::ApplicationModel::Core::CoreApplication::Resuming += ref new Windows::Foundation::EventHandler(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(this, &ApplicationView::OnActivated); applicationView->CoreWindow->VisibilityChanged += ref new TypedEventHandler(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(CreateThread(NULL, (64*1024), //ObjectThreadRootPlatform::s_threadStackSize, reinterpret_cast(objectThreadProc), reinterpret_cast(this), 0, reinterpret_cast(&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 m_window; // (proof of concept) static bool m_done; HANDLE m_thread; unsigned long* m_threadId; }; Platform::Agile 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^ args) { auto applicationViewSource = ref new ApplicationViewSource(); Windows::ApplicationModel::Core::CoreApplication::Run(applicationViewSource); return 0; }