|
|
@@ -4,9 +4,9 @@
|
|
|
#include <QDir>
|
|
|
#include <QFile>
|
|
|
#include <QGuiApplication>
|
|
|
+#include <QOffscreenSurface>
|
|
|
#include <QOpenGLContext>
|
|
|
#include <QOpenGLFunctions>
|
|
|
-#include <QOffscreenSurface>
|
|
|
#include <QQmlApplicationEngine>
|
|
|
#include <QQmlContext>
|
|
|
#include <QQuickWindow>
|
|
|
@@ -14,20 +14,23 @@
|
|
|
#include <QSurfaceFormat>
|
|
|
#include <QTextStream>
|
|
|
#include <QUrl>
|
|
|
+#include <cstdio>
|
|
|
#include <qglobal.h>
|
|
|
#include <qguiapplication.h>
|
|
|
+#include <qnamespace.h>
|
|
|
#include <qobject.h>
|
|
|
#include <qqml.h>
|
|
|
#include <qqmlapplicationengine.h>
|
|
|
#include <qsgrendererinterface.h>
|
|
|
#include <qstringliteral.h>
|
|
|
+#include <qstringview.h>
|
|
|
#include <qsurfaceformat.h>
|
|
|
#include <qurl.h>
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
-#include <windows.h>
|
|
|
#include <QProcess>
|
|
|
#include <gl/gl.h>
|
|
|
+#include <windows.h>
|
|
|
#pragma comment(lib, "opengl32.lib")
|
|
|
#endif
|
|
|
|
|
|
@@ -48,25 +51,25 @@ static bool testNativeOpenGL() {
|
|
|
wc.lpfnWndProc = DefWindowProcA;
|
|
|
wc.hInstance = GetModuleHandle(nullptr);
|
|
|
wc.lpszClassName = "OpenGLTest";
|
|
|
-
|
|
|
+
|
|
|
if (!RegisterClassA(&wc)) {
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
- HWND hwnd = CreateWindowExA(0, "OpenGLTest", "", WS_OVERLAPPEDWINDOW,
|
|
|
- 0, 0, 1, 1, nullptr, nullptr, wc.hInstance, nullptr);
|
|
|
+
|
|
|
+ HWND hwnd = CreateWindowExA(0, "OpenGLTest", "", WS_OVERLAPPEDWINDOW, 0, 0, 1,
|
|
|
+ 1, nullptr, nullptr, wc.hInstance, nullptr);
|
|
|
if (!hwnd) {
|
|
|
UnregisterClassA("OpenGLTest", wc.hInstance);
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
HDC hdc = GetDC(hwnd);
|
|
|
if (!hdc) {
|
|
|
DestroyWindow(hwnd);
|
|
|
UnregisterClassA("OpenGLTest", wc.hInstance);
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
PIXELFORMATDESCRIPTOR pfd = {};
|
|
|
pfd.nSize = sizeof(pfd);
|
|
|
pfd.nVersion = 1;
|
|
|
@@ -76,53 +79,57 @@ static bool testNativeOpenGL() {
|
|
|
pfd.cDepthBits = 24;
|
|
|
pfd.cStencilBits = 8;
|
|
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
|
|
-
|
|
|
+
|
|
|
int pixelFormat = ChoosePixelFormat(hdc, &pfd);
|
|
|
bool success = false;
|
|
|
-
|
|
|
+
|
|
|
if (pixelFormat != 0 && SetPixelFormat(hdc, pixelFormat, &pfd)) {
|
|
|
HGLRC hglrc = wglCreateContext(hdc);
|
|
|
if (hglrc) {
|
|
|
if (wglMakeCurrent(hdc, hglrc)) {
|
|
|
// Successfully created OpenGL context
|
|
|
- const char* vendor = (const char*)glGetString(GL_VENDOR);
|
|
|
- const char* renderer = (const char*)glGetString(GL_RENDERER);
|
|
|
- const char* version = (const char*)glGetString(GL_VERSION);
|
|
|
-
|
|
|
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
|
|
|
+ const char *renderer = (const char *)glGetString(GL_RENDERER);
|
|
|
+ const char *version = (const char *)glGetString(GL_VERSION);
|
|
|
+
|
|
|
if (vendor && renderer && version) {
|
|
|
- fprintf(stderr, "[OpenGL Test] Native context created successfully\n");
|
|
|
+ fprintf(stderr,
|
|
|
+ "[OpenGL Test] Native context created successfully\n");
|
|
|
fprintf(stderr, "[OpenGL Test] Vendor: %s\n", vendor);
|
|
|
fprintf(stderr, "[OpenGL Test] Renderer: %s\n", renderer);
|
|
|
fprintf(stderr, "[OpenGL Test] Version: %s\n", version);
|
|
|
success = true;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
wglMakeCurrent(nullptr, nullptr);
|
|
|
}
|
|
|
wglDeleteContext(hglrc);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
DestroyWindow(hwnd);
|
|
|
UnregisterClassA("OpenGLTest", wc.hInstance);
|
|
|
-
|
|
|
+
|
|
|
return success;
|
|
|
}
|
|
|
|
|
|
// Windows crash handler to detect OpenGL failures and suggest fallback
|
|
|
static bool g_opengl_crashed = false;
|
|
|
-static LONG WINAPI crashHandler(EXCEPTION_POINTERS* exceptionInfo) {
|
|
|
- if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
|
|
+static LONG WINAPI crashHandler(EXCEPTION_POINTERS *exceptionInfo) {
|
|
|
+ if (exceptionInfo->ExceptionRecord->ExceptionCode ==
|
|
|
+ EXCEPTION_ACCESS_VIOLATION) {
|
|
|
// Log crash
|
|
|
- FILE* crash_log = fopen("opengl_crash.txt", "w");
|
|
|
+ FILE *crash_log = fopen("opengl_crash.txt", "w");
|
|
|
if (crash_log) {
|
|
|
- fprintf(crash_log, "OpenGL/Qt rendering crash detected (Access Violation)\n");
|
|
|
+ fprintf(crash_log,
|
|
|
+ "OpenGL/Qt rendering crash detected (Access Violation)\n");
|
|
|
fprintf(crash_log, "Try running with: run_debug_softwaregl.cmd\n");
|
|
|
- fprintf(crash_log, "Or set environment variable: QT_QUICK_BACKEND=software\n");
|
|
|
+ fprintf(crash_log,
|
|
|
+ "Or set environment variable: QT_QUICK_BACKEND=software\n");
|
|
|
fclose(crash_log);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
qCritical() << "=== CRASH DETECTED ===";
|
|
|
qCritical() << "OpenGL rendering failed. This usually means:";
|
|
|
qCritical() << "1. Graphics drivers are outdated";
|
|
|
@@ -131,7 +138,7 @@ static LONG WINAPI crashHandler(EXCEPTION_POINTERS* exceptionInfo) {
|
|
|
qCritical() << "";
|
|
|
qCritical() << "To fix: Run run_debug_softwaregl.cmd instead";
|
|
|
qCritical() << "Or set: set QT_QUICK_BACKEND=software";
|
|
|
-
|
|
|
+
|
|
|
g_opengl_crashed = true;
|
|
|
}
|
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
|
@@ -142,11 +149,11 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
#ifdef Q_OS_WIN
|
|
|
// Install crash handler to detect OpenGL failures
|
|
|
SetUnhandledExceptionFilter(crashHandler);
|
|
|
-
|
|
|
+
|
|
|
// Test OpenGL BEFORE any Qt initialization (using native Win32 API)
|
|
|
fprintf(stderr, "[Pre-Init] Testing native OpenGL availability...\n");
|
|
|
bool opengl_available = testNativeOpenGL();
|
|
|
-
|
|
|
+
|
|
|
if (!opengl_available) {
|
|
|
fprintf(stderr, "[Pre-Init] WARNING: OpenGL test failed!\n");
|
|
|
fprintf(stderr, "[Pre-Init] Forcing software rendering mode\n");
|
|
|
@@ -155,11 +162,11 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
} else {
|
|
|
fprintf(stderr, "[Pre-Init] OpenGL test passed\n");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Check if we should use software rendering
|
|
|
bool use_software = qEnvironmentVariableIsSet("QT_QUICK_BACKEND") &&
|
|
|
qEnvironmentVariable("QT_QUICK_BACKEND") == "software";
|
|
|
-
|
|
|
+
|
|
|
if (use_software) {
|
|
|
qInfo() << "=== SOFTWARE RENDERING MODE ===";
|
|
|
qInfo() << "Using Qt Quick Software renderer (CPU-based)";
|
|
|
@@ -168,34 +175,43 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
#endif
|
|
|
|
|
|
// Setup message handler for debugging
|
|
|
- qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
|
|
- QByteArray localMsg = msg.toLocal8Bit();
|
|
|
- const char *file = context.file ? context.file : "";
|
|
|
- const char *function = context.function ? context.function : "";
|
|
|
-
|
|
|
+ qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &context,
|
|
|
+ const QString &msg) {
|
|
|
+ QByteArray const localMsg = msg.toLocal8Bit();
|
|
|
+ const char *file = (context.file != nullptr) ? context.file : "";
|
|
|
+ const char *function =
|
|
|
+ (context.function != nullptr) ? context.function : "";
|
|
|
+
|
|
|
FILE *out = stderr;
|
|
|
switch (type) {
|
|
|
case QtDebugMsg:
|
|
|
- fprintf(out, "[DEBUG] %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
|
+ fprintf(out, "[DEBUG] %s (%s:%u, %s)\n", localMsg.constData(), file,
|
|
|
+ context.line, function);
|
|
|
break;
|
|
|
case QtInfoMsg:
|
|
|
fprintf(out, "[INFO] %s\n", localMsg.constData());
|
|
|
break;
|
|
|
case QtWarningMsg:
|
|
|
- fprintf(out, "[WARNING] %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
|
+ fprintf(out, "[WARNING] %s (%s:%u, %s)\n", localMsg.constData(), file,
|
|
|
+ context.line, function);
|
|
|
// Check for critical OpenGL warnings
|
|
|
- if (msg.contains("OpenGL", Qt::CaseInsensitive) ||
|
|
|
+ if (msg.contains("OpenGL", Qt::CaseInsensitive) ||
|
|
|
msg.contains("scene graph", Qt::CaseInsensitive) ||
|
|
|
msg.contains("RHI", Qt::CaseInsensitive)) {
|
|
|
- fprintf(out, "[HINT] If you see crashes, try software rendering: set QT_QUICK_BACKEND=software\n");
|
|
|
+ fprintf(out, "[HINT] If you see crashes, try software rendering: set "
|
|
|
+ "QT_QUICK_BACKEND=software\n");
|
|
|
}
|
|
|
break;
|
|
|
case QtCriticalMsg:
|
|
|
- fprintf(out, "[CRITICAL] %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
|
- fprintf(out, "[CRITICAL] Try running with software rendering if this persists\n");
|
|
|
+ fprintf(out, "[CRITICAL] %s (%s:%u, %s)\n", localMsg.constData(), file,
|
|
|
+ context.line, function);
|
|
|
+ fprintf(
|
|
|
+ out,
|
|
|
+ "[CRITICAL] Try running with software rendering if this persists\n");
|
|
|
break;
|
|
|
case QtFatalMsg:
|
|
|
- fprintf(out, "[FATAL] %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
|
+ fprintf(out, "[FATAL] %s (%s:%u, %s)\n", localMsg.constData(), file,
|
|
|
+ context.line, function);
|
|
|
fprintf(out, "[FATAL] === RECOVERY SUGGESTION ===\n");
|
|
|
fprintf(out, "[FATAL] Run: run_debug_softwaregl.cmd\n");
|
|
|
fprintf(out, "[FATAL] Or set: QT_QUICK_BACKEND=software\n");
|
|
|
@@ -206,7 +222,7 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
|
|
|
qInfo() << "=== Standard of Iron - Starting ===";
|
|
|
qInfo() << "Qt version:" << QT_VERSION_STR;
|
|
|
-
|
|
|
+
|
|
|
// Linux-specific: prefer X11 over Wayland for better OpenGL compatibility
|
|
|
#ifndef Q_OS_WIN
|
|
|
if (qEnvironmentVariableIsSet("WAYLAND_DISPLAY") &&
|
|
|
@@ -232,21 +248,22 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
fmt.setDepthBufferSize(k_depth_buffer_bits);
|
|
|
fmt.setStencilBufferSize(k_stencil_buffer_bits);
|
|
|
fmt.setSamples(0);
|
|
|
-
|
|
|
+
|
|
|
#ifdef Q_OS_WIN
|
|
|
// Windows: Request compatibility profile for better driver support
|
|
|
// Some Windows drivers have issues with Core profile on older hardware
|
|
|
fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
|
|
|
qInfo() << "Windows detected: Using OpenGL Compatibility Profile";
|
|
|
#endif
|
|
|
-
|
|
|
+
|
|
|
QSurfaceFormat::setDefaultFormat(fmt);
|
|
|
- qInfo() << "Surface format configured: OpenGL" << fmt.majorVersion() << "." << fmt.minorVersion();
|
|
|
+ qInfo() << "Surface format configured: OpenGL" << fmt.majorVersion() << "."
|
|
|
+ << fmt.minorVersion();
|
|
|
|
|
|
qInfo() << "Creating QGuiApplication...";
|
|
|
QGuiApplication app(argc, argv);
|
|
|
qInfo() << "QGuiApplication created successfully";
|
|
|
-
|
|
|
+
|
|
|
qInfo() << "Creating LanguageManager...";
|
|
|
auto *language_manager = new LanguageManager();
|
|
|
qInfo() << "LanguageManager created";
|
|
|
@@ -273,13 +290,14 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
qInfo() << "Loading Main.qml...";
|
|
|
qInfo() << "Loading Main.qml...";
|
|
|
engine.load(QUrl(QStringLiteral("qrc:/StandardOfIron/ui/qml/Main.qml")));
|
|
|
-
|
|
|
+
|
|
|
qInfo() << "Checking if QML loaded...";
|
|
|
if (engine.rootObjects().isEmpty()) {
|
|
|
qWarning() << "Failed to load QML file";
|
|
|
return -1;
|
|
|
}
|
|
|
- qInfo() << "QML loaded successfully, root objects count:" << engine.rootObjects().size();
|
|
|
+ qInfo() << "QML loaded successfully, root objects count:"
|
|
|
+ << engine.rootObjects().size();
|
|
|
|
|
|
qInfo() << "Finding QQuickWindow...";
|
|
|
auto *root_obj = engine.rootObjects().first();
|
|
|
@@ -340,9 +358,9 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
});
|
|
|
|
|
|
qInfo() << "Starting event loop...";
|
|
|
-
|
|
|
- int result = QGuiApplication::exec();
|
|
|
-
|
|
|
+
|
|
|
+ int const result = QGuiApplication::exec();
|
|
|
+
|
|
|
#ifdef Q_OS_WIN
|
|
|
// Check if we crashed during OpenGL initialization
|
|
|
if (g_opengl_crashed) {
|
|
|
@@ -352,7 +370,8 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
qCritical() << "========================================";
|
|
|
qCritical() << "";
|
|
|
qCritical() << "The application crashed during OpenGL initialization.";
|
|
|
- qCritical() << "This is a known issue with Qt + some Windows graphics drivers.";
|
|
|
+ qCritical()
|
|
|
+ << "This is a known issue with Qt + some Windows graphics drivers.";
|
|
|
qCritical() << "";
|
|
|
qCritical() << "SOLUTION: Set environment variable before running:";
|
|
|
qCritical() << " set QT_QUICK_BACKEND=software";
|
|
|
@@ -363,6 +382,6 @@ auto main(int argc, char *argv[]) -> int {
|
|
|
return -1;
|
|
|
}
|
|
|
#endif
|
|
|
-
|
|
|
+
|
|
|
return result;
|
|
|
}
|