#define GLFW_INCLUDE_NONE #include #include #include #ifdef USE_D3D11 #include #define GLFW_EXPOSE_NATIVE_WIN32 #include #include static ID3D11Device* d3dDevice = nullptr; static ID3D11DeviceContext* d3dDeviceContext = nullptr; static IDXGISwapChain* d3dSwapChain = nullptr; static ID3D11RenderTargetView* d3dRenderTargetView = nullptr; // Forward declarations of helper functions bool InitD3D(HWND hWnd); void CleanupD3D(); bool ResizeD3D(GLFWwindow* window, int width, int height); #else #include #include #endif #ifdef __SWITCH__ #include extern "C" void userAppInit() { socketInitializeDefault(); nxlinkStdio(); appletSetWirelessPriorityMode(AppletWirelessPriorityMode_OptimizedForWlan); plInitialize(PlServiceType_User); } extern "C" void userAppExit() { plExit(); socketExit(); } #endif static int osdShow = 0; static void die(const char* msg) { fprintf(stderr, "%s\n", msg); exit(1); } // Main code int main(int argc, char* argv[]) { if (argc < 2) die("missing file path"); if (!glfwInit()) die("init glfw failed"); // Create window with graphics context GLFWwindow* window = glfwCreateWindow(1280, 720, argv[1], nullptr, nullptr); if (!window) { glfwTerminate(); return -1; } glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, 1); else if (key == GLFW_KEY_ENTER) osdShow = !osdShow; } }); #ifdef USE_D3D11 // Initialize Direct3D HWND hwnd = glfwGetWin32Window(window); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); if (!InitD3D(hwnd)) die("init dx11 failed"); glfwSetFramebufferSizeCallback(window, (GLFWframebuffersizefun)ResizeD3D); #else glfwMakeContextCurrent(window); // Load OpenGL routines using glad gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); glfwSwapInterval(1); glfwSetTime(0); #endif int fbw = 0, fbh = 0; // Main loop while (!glfwWindowShouldClose(window)) { glfwGetFramebufferSize(window, &fbw, &fbh); #ifdef USE_D3D11 float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; d3dDeviceContext->OMSetRenderTargets(1, &d3dRenderTargetView, nullptr); d3dDeviceContext->ClearRenderTargetView(d3dRenderTargetView, clear_color); d3dSwapChain->Present(1, 0); // Present with vsync #else glViewport(0, 0, fbw, fbh); glfwSwapBuffers(window); #endif glfwWaitEvents(); } #ifdef USE_D3D11 CleanupD3D(); #endif glfwDestroyWindow(window); glfwTerminate(); return 0; } #ifdef USE_D3D11 bool InitD3D(HWND hWnd) { static const D3D_DRIVER_TYPE driverAttempts[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; static const D3D_FEATURE_LEVEL levelAttempts[] = { D3D_FEATURE_LEVEL_11_1, // Direct3D 11.1 SM 6 D3D_FEATURE_LEVEL_11_0, // Direct3D 11.0 SM 5 D3D_FEATURE_LEVEL_10_1, // Direct3D 10.1 SM 4 }; HRESULT hr = S_OK; // Setup swap chain DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 2; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for (size_t i = 0; i < ARRAYSIZE(driverAttempts); i++) { hr = D3D11CreateDeviceAndSwapChain(nullptr, driverAttempts[i], nullptr, 0, levelAttempts, ARRAYSIZE(levelAttempts), D3D11_SDK_VERSION, &sd, &d3dSwapChain, &d3dDevice, nullptr, &d3dDeviceContext); if (SUCCEEDED(hr)) break; } if (FAILED(hr)) { CleanupD3D(); return false; } return ResizeD3D(nullptr, 0, 0); } void CleanupD3D() { if (d3dRenderTargetView) d3dRenderTargetView->Release(); if (d3dSwapChain) d3dSwapChain->Release(); if (d3dDeviceContext) d3dDeviceContext->Release(); if (d3dDevice) d3dDevice->Release(); } bool ResizeD3D(GLFWwindow* window, int width, int height) { ID3D11Texture2D* backBuffer = nullptr; HRESULT hr = S_OK; if (d3dRenderTargetView) d3dRenderTargetView->Release(); // Resize render target buffers if (width > 0 && height > 0) { hr = d3dSwapChain->ResizeBuffers(2, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, 0); if (FAILED(hr)) return false; } hr = d3dSwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)); if (FAILED(hr)) return false; hr = d3dDevice->CreateRenderTargetView(backBuffer, nullptr, &d3dRenderTargetView); backBuffer->Release(); return SUCCEEDED(hr); } #endif