#include #include #include #include #include #include #include "XCEngine/RHI/OpenGL/OpenGLDevice.h" #include "XCEngine/RHI/OpenGL/OpenGLSwapChain.h" #include "XCEngine/RHI/OpenGL/OpenGLCommandList.h" #include "XCEngine/Debug/Logger.h" #include "XCEngine/Debug/ConsoleLogSink.h" #include "XCEngine/Containers/String.h" #pragma comment(lib, "opengl32.lib") using namespace XCEngine::RHI; using namespace XCEngine::Debug; using namespace XCEngine::Containers; static const int gWidth = 1280; static const int gHeight = 720; void Log(const char* format, ...) { char buffer[1024]; va_list args; va_start(args, format); vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); Logger::Get().Debug(LogCategory::Rendering, String(buffer)); } void SaveScreenshotPPM(const char* filename, int width, int height) { unsigned char* pixels = (unsigned char*)malloc(width * height * 3); if (!pixels) { Log("[ERROR] Failed to allocate pixel buffer"); return; } glFinish(); glReadBuffer(GL_BACK); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); FILE* f = fopen(filename, "wb"); if (!f) { Log("[ERROR] Failed to open file for screenshot: %s", filename); free(pixels); return; } fprintf(f, "P6\n%d %d\n255\n", width, height); unsigned char* row = (unsigned char*)malloc(width * 3); for (int y = height - 1; y >= 0; y--) { memcpy(row, pixels + y * width * 3, width * 3); fwrite(row, 1, width * 3, f); } free(row); free(pixels); fclose(f); Log("[INFO] Screenshot saved to %s", filename); } LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CLOSE: PostQuitMessage(0); break; } return DefWindowProc(hwnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // Initialize logger Logger::Get().Initialize(); Logger::Get().AddSink(std::make_unique()); Logger::Get().SetMinimumLevel(LogLevel::Debug); Log("[INFO] OpenGL Integration Test Starting"); // Register window class WNDCLASSEXW wc = {}; wc.cbSize = sizeof(WNDCLASSEXW); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = L"XCEngine_OpenGL_Test"; if (!RegisterClassExW(&wc)) { Log("[ERROR] Failed to register window class"); return -1; } // Calculate full window size from client area size RECT rect = { 0, 0, gWidth, gHeight }; AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); // Create window HWND hwnd = CreateWindowExW( 0, L"XCEngine_OpenGL_Test", L"OpenGL Integration Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL ); if (!hwnd) { Log("[ERROR] Failed to create window"); return -1; } // Initialize OpenGL device with existing window OpenGLDevice device; if (!device.InitializeWithExistingWindow(hwnd)) { Log("[ERROR] Failed to initialize OpenGL device"); return -1; } ShowWindow(hwnd, nShowCmd); UpdateWindow(hwnd); // Log OpenGL device info Log("[INFO] OpenGL Device: %S", device.GetDeviceInfo().renderer.c_str()); Log("[INFO] OpenGL Version: %S", device.GetDeviceInfo().version.c_str()); // Create swap chain for rendering OpenGLSwapChain swapChain; swapChain.Initialize(hwnd, gWidth, gHeight); // Create command list for rendering commands OpenGLCommandList commandList; // Main render loop MSG msg = {}; int frameCount = 0; const int targetFrameCount = 30; while (frameCount < targetFrameCount) { if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { break; } TranslateMessage(&msg); DispatchMessageW(&msg); } else { // Set viewport and clear color using encapsulated command list commandList.SetViewport(0, 0, gWidth, gHeight); commandList.Clear(1.0f, 0.0f, 0.0f, 1.0f, 1 | 2); // Present the rendered frame swapChain.Present(0, 0); frameCount++; } } // Take screenshot after target frame count is reached // glFinish ensures all OpenGL commands are completed before reading pixels Log("[INFO] Reached target frame count %d - taking screenshot!", targetFrameCount); SaveScreenshotPPM("minimal.ppm", gWidth, gHeight); // Shutdown in reverse order of initialization swapChain.Shutdown(); device.Shutdown(); Logger::Get().Shutdown(); Log("[INFO] OpenGL Integration Test Finished"); return 0; }