1
0
Files
xplayer/main.cpp
2023-08-29 10:06:18 +08:00

173 lines
4.8 KiB
C++

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <cstdio>
#include <cstdlib>
#ifdef USE_D3D11
#include <mpv/render_dxgi.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>
#include <d3d11.h>
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 <mpv/render_gl.h>
#include <glad/glad.h>
#endif
#ifdef __SWITCH__
#include <switch.h>
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