diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a7cd45ae37..8789fcde1c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1659,7 +1659,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. static const QString TESTER = "HIFI_TESTER"; auto gpuIdent = GPUIdent::getInstance(); - auto glContextData = getGLContextData(); + auto glContextData = gl::ContextInfo::get(); QJsonObject properties = { { "version", applicationVersion() }, { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) || isTester }, @@ -1676,11 +1676,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo { "gpu_name", gpuIdent->getName() }, { "gpu_driver", gpuIdent->getDriver() }, { "gpu_memory", static_cast(gpuIdent->getMemory()) }, - { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, - { "gl_version", glContextData["version"] }, - { "gl_vender", glContextData["vendor"] }, - { "gl_sl_version", glContextData["sl_version"] }, - { "gl_renderer", glContextData["renderer"] }, + { "gl_version_int", glVersionToInteger(glContextData.version.c_str()) }, + { "gl_version", glContextData.version.c_str() }, + { "gl_vender", glContextData.vendor.c_str() }, + { "gl_sl_version", glContextData.shadingLanguageVersion.c_str() }, + { "gl_renderer", glContextData.renderer.c_str() }, { "ideal_thread_count", QThread::idealThreadCount() } }; auto macVersion = QSysInfo::macVersion(); @@ -2282,8 +2282,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); - auto glInfo = getGLContextData(); - properties["gl_info"] = glInfo; + auto contextInfo = gl::ContextInfo::get(); + properties["gl_info"] = QJsonObject{ + { "version", contextInfo.version.c_str() }, + { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, + { "vendor", contextInfo.vendor.c_str() }, + { "renderer", contextInfo.renderer.c_str() }, + }; properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemSize()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemSize()); properties["gpu_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerGPUAverage()); @@ -2996,6 +3001,9 @@ void Application::initializeGL() { qCWarning(interfaceapp, "Unable to make window context current"); } + // Populate the global OpenGL context based on the information for the primary window GL context + gl::ContextInfo::get(true); + #if !defined(DISABLE_QML) QStringList chromiumFlags; // HACK: re-expose mic and camera to prevent crash on domain-change in chromium's media::FakeAudioInputStream::ReadAudioFromSource() diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index c9f17b686d..b2c98e91d3 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -148,6 +148,33 @@ static bool setupPixelFormatSimple(HDC hdc) { #endif + +const gl::ContextInfo& gl::ContextInfo::get(bool init) { + static gl::ContextInfo INSTANCE; + if (init) { + static std::once_flag once; + std::call_once(once, [&] { + INSTANCE.init(); + }); + } + return INSTANCE; +} + +gl::ContextInfo& gl::ContextInfo::init() { + if (glGetString) { + version = (const char*)glGetString(GL_VERSION); + shadingLanguageVersion = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + vendor = (const char*)glGetString(GL_VENDOR); + renderer = (const char*)glGetString(GL_RENDERER); + GLint n = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &n); + for (GLint i = 0; i < n; ++i) { + extensions.emplace_back((const char*)glGetStringi(GL_EXTENSIONS, i)); + } + } + return *this; +} + uint16_t gl::getAvailableVersion() { static uint8_t major = 0, minor = 0; static std::once_flag once; @@ -277,25 +304,6 @@ int glVersionToInteger(QString glVersion) { return (majorNumber << 16) | minorNumber; } -QJsonObject getGLContextData() { - static QJsonObject result; - static std::once_flag once; - std::call_once(once, [] { - QString glVersion = QString((const char*)glGetString(GL_VERSION)); - QString glslVersion = QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - QString glVendor = QString((const char*) glGetString(GL_VENDOR)); - QString glRenderer = QString((const char*)glGetString(GL_RENDERER)); - - result = QJsonObject { - { "version", glVersion }, - { "sl_version", glslVersion }, - { "vendor", glVendor }, - { "renderer", glRenderer }, - }; - }); - return result; -} - QThread* RENDER_THREAD = nullptr; bool isRenderThread() { diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index c09f9d4963..05687b2a8a 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -29,7 +29,6 @@ class QGLFormat; size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format); const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); -QJsonObject getGLContextData(); int glVersionToInteger(QString glVersion); bool isRenderThread(); @@ -39,6 +38,26 @@ bool isRenderThread(); #define GL_GET_MAJOR_VERSION(glversion) ((glversion & 0xFF00) >> 8) namespace gl { + struct ContextInfo { + std::string version; + std::string shadingLanguageVersion; + std::string vendor; + std::string renderer; + std::vector extensions; + + ContextInfo& init(); + operator bool() const { return !version.empty(); } + + static const ContextInfo& get(bool init = false); + }; + +#define LOG_GL_CONTEXT_INFO(category, contextInfo) \ + qCDebug(category) << "GL Version: " << contextInfo.version.c_str(); \ + qCDebug(category) << "GL Shader Language Version: " << contextInfo.shadingLanguageVersion.c_str(); \ + qCDebug(category) << "GL Vendor: " << contextInfo.vendor.c_str(); \ + qCDebug(category) << "GL Renderer: " << contextInfo.renderer.c_str(); + + void globalLock(); void globalRelease(bool finish = true); diff --git a/libraries/gl/src/gl/GLWindow.cpp b/libraries/gl/src/gl/GLWindow.cpp index 7930e050de..19f8428d0a 100644 --- a/libraries/gl/src/gl/GLWindow.cpp +++ b/libraries/gl/src/gl/GLWindow.cpp @@ -33,14 +33,12 @@ GLWindow::~GLWindow() { bool GLWindow::makeCurrent() { bool makeCurrentResult = _context->makeCurrent(); Q_ASSERT(makeCurrentResult); - - std::call_once(_reportOnce, []{ - qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); - }); - + + if (makeCurrentResult) { + std::call_once(_reportOnce, []{ + LOG_GL_CONTEXT_INFO(glLogging, gl::ContextInfo().init()); + }); + } return makeCurrentResult; } diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index 69b41da821..c5b8baa6d4 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -73,13 +73,9 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) { bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - if (glGetString) { + if (result) { std::call_once(_reportOnce, [] { - qCDebug(glLogging) << "GL Version: " << QString((const char*)glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " - << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*)glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*)glGetString(GL_RENDERER)); + LOG_GL_CONTEXT_INFO(glLogging, gl::ContextInfo().init()); }); } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index fef458f536..3e5043003b 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -117,9 +117,10 @@ void GLBackend::init() { static std::once_flag once; std::call_once(once, [] { - - QString vendor{ (const char*)glGetString(GL_VENDOR) }; - QString renderer{ (const char*)glGetString(GL_RENDERER) }; + ::gl::ContextInfo contextInfo; + contextInfo.init(); + QString vendor { contextInfo.vendor.c_str() }; + QString renderer { contextInfo.renderer.c_str() }; // Textures GL_GET_INTEGER(MAX_TEXTURE_IMAGE_UNITS); @@ -131,10 +132,7 @@ void GLBackend::init() { GL_GET_INTEGER(MAX_UNIFORM_BLOCK_SIZE); GL_GET_INTEGER(UNIFORM_BUFFER_OFFSET_ALIGNMENT); - qCDebug(gpugllogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(gpugllogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(gpugllogging) << "GL Vendor: " << vendor; - qCDebug(gpugllogging) << "GL Renderer: " << renderer; + LOG_GL_CONTEXT_INFO(gpugllogging, contextInfo); GPUIdent* gpu = GPUIdent::getInstance(vendor, renderer); // From here on, GPUIdent::getInstance()->getMumble() should efficiently give the same answers. qCDebug(gpugllogging) << "GPU:"; diff --git a/libraries/platform/CMakeLists.txt b/libraries/platform/CMakeLists.txt index f0dce500f4..0d984f9684 100644 --- a/libraries/platform/CMakeLists.txt +++ b/libraries/platform/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME platform) setup_hifi_library() -link_hifi_libraries(shared) +link_hifi_libraries(shared gl) GroupSources("src") target_json() @@ -15,4 +15,4 @@ if (APPLE) elseif(WIN32) target_link_libraries(${TARGET_NAME} Iphlpapi.lib) -endif () \ No newline at end of file +endif() \ No newline at end of file diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 5008a4f6ce..9bd9d47890 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -34,6 +34,43 @@ namespace platform { namespace keys{ extern const char* displays; extern const char* isMaster; } + namespace graphicsAPI { + extern const char* name; + extern const char* version; + extern const char* apiOpenGL; + extern const char* apiVulkan; + extern const char* apiDirect3D11; + extern const char* apiDirect3D12; + extern const char* apiMetal; + namespace gl { + extern const char* shadingLanguageVersion; + extern const char* vendor; + extern const char* renderer; + extern const char* extensions; + } + namespace vk { + extern const char* devices; + namespace device { + extern const char* apiVersion; + extern const char* driverVersion; + extern const char* deviceType; + extern const char* vendor; + extern const char* name; + extern const char* formats; + extern const char* extensions; + extern const char* queues; + extern const char* heaps; + namespace heap { + extern const char* flags; + extern const char* size; + } + namespace queue { + extern const char* flags; + extern const char* count; + } + } + } + } namespace nic { extern const char* mac; extern const char* name; @@ -78,6 +115,7 @@ namespace platform { namespace keys{ // Keys for categories used in json returned by getAll() extern const char* CPUS; extern const char* GPUS; + extern const char* GRAPHICS_APIS; extern const char* DISPLAYS; extern const char* NICS; extern const char* MEMORY; diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 66c9cd2c5d..5a7b40f71b 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -322,3 +322,8 @@ void MACOSInstance::enumerateComputer(){ } +void MACOSInstance::enumerateGraphicsApis() { + Instance::enumerateGraphicsApis(); + + // TODO imeplement Metal query +} diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.h b/libraries/platform/src/platform/backend/MACOSPlatform.h index f249dad001..87c16972ec 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.h +++ b/libraries/platform/src/platform/backend/MACOSPlatform.h @@ -19,6 +19,7 @@ namespace platform { void enumerateGpusAndDisplays() override; void enumerateMemory() override; void enumerateComputer() override; + void enumerateGraphicsApis() override; }; } // namespace platform diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 17d9d8019e..c3abcce5f1 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -35,6 +35,45 @@ namespace platform { namespace keys { const char* displays = "displays"; const char* isMaster = "isMaster"; } + namespace graphicsAPI { + const char* name = "name"; + const char* version = "version"; + + const char* apiOpenGL = "OpenGL"; + const char* apiVulkan = "Vulkan"; + const char* apiDirect3D11 = "D3D11"; + const char* apiDirect3D12 = "D3D12"; + const char* apiMetal = "Metal"; + + namespace gl { + const char* shadingLanguageVersion = "shadingLanguageVersion"; + const char* vendor = "vendor"; + const char* renderer = "renderer"; + const char* extensions = "extensions"; + } + namespace vk { + const char* devices = "devices"; + namespace device { + const char* apiVersion = "apiVersion"; + const char* driverVersion = "driverVersion"; + const char* deviceType = "deviceType"; + const char* vendor = "vendor"; + const char* name = "name"; + const char* formats = "formats"; + const char* extensions = "extensions"; + const char* heaps = "heaps"; + namespace heap { + const char* flags = "flags"; + const char* size = "size"; + } + const char* queues = "queues"; + namespace queue { + const char* flags = "flags"; + const char* count = "count"; + } + } + } + } namespace nic { const char* mac = "mac"; const char* name = "name"; @@ -78,6 +117,7 @@ namespace platform { namespace keys { const char* CPUS = "cpus"; const char* GPUS = "gpus"; + const char* GRAPHICS_APIS = "graphicsAPIs"; const char* DISPLAYS = "displays"; const char* NICS = "nics"; const char* MEMORY = "memory"; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index e02eaf2837..114a53d2cc 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -10,9 +10,18 @@ #include "PlatformInstance.h" #include +#include #include "../PlatformKeys.h" #include "../Profiler.h" +// For testing the vulkan dump +//#define HAVE_VULKAN 1 +//#pragma comment(lib, "C:\\VulkanSDK\\1.1.101.0\\Lib\\vulkan-1.lib") + +#ifdef HAVE_VULKAN +#include +#endif + using namespace platform; bool Instance::enumeratePlatform() { @@ -30,6 +39,7 @@ bool Instance::enumeratePlatform() { enumerateCpus(); enumerateGpusAndDisplays(); enumerateNics(); + enumerateGraphicsApis(); // eval the master index for each platform scopes updateMasterIndices(); @@ -105,6 +115,74 @@ void Instance::enumerateNics() { } } +#if defined(HAVE_VULKAN) +static std::string vkVersionToString(uint32_t version) { + return QString("%1.%2.%3").arg(VK_VERSION_MAJOR(version)).arg(VK_VERSION_MINOR(version)).arg(VK_VERSION_PATCH(version)).toStdString(); +} +#endif + + +void Instance::enumerateGraphicsApis() { + // OpenGL rendering API is supported on all platforms + { + auto& glContextInfo = gl::ContextInfo::get(); + json gl; + gl[keys::graphicsAPI::name] = keys::graphicsAPI::apiOpenGL; + gl[keys::graphicsAPI::version] = glContextInfo.version; + gl[keys::graphicsAPI::gl::vendor] = glContextInfo.vendor; + gl[keys::graphicsAPI::gl::renderer] = glContextInfo.renderer; + gl[keys::graphicsAPI::gl::shadingLanguageVersion] = glContextInfo.shadingLanguageVersion; + gl[keys::graphicsAPI::gl::extensions] = glContextInfo.extensions; + _graphicsApis.push_back(gl); + } + +#if defined(HAVE_VULKAN) + // Vulkan rendering API is supported on all platforms (sort of) + { + try { + vk::ApplicationInfo appInfo{ "Interface", 1, "Luci", 1, VK_API_VERSION_1_1 }; + auto instancePtr = vk::createInstanceUnique({ {}, &appInfo }); + if (instancePtr) { + json vkinfo; + const auto& vkinstance = *instancePtr; + vkinfo[keys::graphicsAPI::name] = keys::graphicsAPI::apiVulkan; + vkinfo[keys::graphicsAPI::version] = vkVersionToString(VK_API_VERSION_1_1); + for (const auto& physicalDevice : vkinstance.enumeratePhysicalDevices()) { + json vkdevice; + auto properties = physicalDevice.getProperties(); + vkdevice[keys::graphicsAPI::vk::device::driverVersion] = vkVersionToString(properties.driverVersion); + vkdevice[keys::graphicsAPI::vk::device::apiVersion] = vkVersionToString(properties.apiVersion); + vkdevice[keys::graphicsAPI::vk::device::deviceType] = vk::to_string(properties.deviceType); + vkdevice[keys::graphicsAPI::vk::device::vendor] = properties.vendorID; + vkdevice[keys::graphicsAPI::vk::device::name] = properties.deviceName; + for (const auto& extensionProperties : physicalDevice.enumerateDeviceExtensionProperties()) { + vkdevice[keys::graphicsAPI::vk::device::extensions].push_back(extensionProperties.extensionName); + } + + for (const auto& queueFamilyProperties : physicalDevice.getQueueFamilyProperties()) { + json vkqueuefamily; + vkqueuefamily[keys::graphicsAPI::vk::device::queue::flags] = vk::to_string(queueFamilyProperties.queueFlags); + vkqueuefamily[keys::graphicsAPI::vk::device::queue::count] = queueFamilyProperties.queueCount; + vkdevice[keys::graphicsAPI::vk::device::queues].push_back(vkqueuefamily); + } + auto memoryProperties = physicalDevice.getMemoryProperties(); + for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex) { + json vkmemoryheap; + const auto& heap = memoryProperties.memoryHeaps[heapIndex]; + vkmemoryheap[keys::graphicsAPI::vk::device::heap::flags] = vk::to_string(heap.flags); + vkmemoryheap[keys::graphicsAPI::vk::device::heap::size] = heap.size; + vkdevice[keys::graphicsAPI::vk::device::heaps].push_back(vkmemoryheap); + } + vkinfo[keys::graphicsAPI::vk::devices].push_back(vkdevice); + } + _graphicsApis.push_back(vkinfo); + } + } catch (const std::runtime_error&) { + } + } +#endif +} + json Instance::getCPU(int index) { assert(index < (int)_cpus.size()); @@ -166,6 +244,14 @@ json Instance::listAllKeys() { keys::gpu::driver, keys::gpu::displays, + keys::graphicsAPI::version, + keys::graphicsAPI::name, + + keys::graphicsAPI::gl::shadingLanguageVersion, + keys::graphicsAPI::gl::vendor, + keys::graphicsAPI::gl::renderer, + keys::graphicsAPI::gl::extensions, + keys::display::boundsLeft, keys::display::boundsRight, keys::display::boundsTop, @@ -187,6 +273,7 @@ json Instance::listAllKeys() { keys::CPUS, keys::GPUS, + keys::GRAPHICS_APIS, keys::DISPLAYS, keys::MEMORY, keys::COMPUTER, @@ -218,6 +305,7 @@ json Instance::getAll() { all[keys::MEMORY] = _memory; all[keys::CPUS] = _cpus; all[keys::GPUS] = _gpus; + all[keys::GRAPHICS_APIS] = _graphicsApis; all[keys::DISPLAYS] = _displays; all[keys::NICS] = _nics; diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 069124853e..2b263c21ef 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -44,6 +44,7 @@ public: void virtual enumerateNics(); void virtual enumerateMemory() = 0; void virtual enumerateComputer()=0; + virtual void enumerateGraphicsApis(); virtual ~Instance(); @@ -57,6 +58,7 @@ protected: std::vector _gpus; std::vector _displays; std::vector _nics; + json _graphicsApis; json _memory; json _computer; diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index e528618fe1..8c0bb1b9aa 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -251,3 +251,9 @@ void WINInstance::enumerateNics() { } #endif } + +void WINInstance::enumerateGraphicsApis() { + Instance::enumerateGraphicsApis(); + + // TODO imeplement D3D 11/12 queries +} diff --git a/libraries/platform/src/platform/backend/WINPlatform.h b/libraries/platform/src/platform/backend/WINPlatform.h index cc56ebfbbc..dd29d696dc 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.h +++ b/libraries/platform/src/platform/backend/WINPlatform.h @@ -20,6 +20,7 @@ namespace platform { void enumerateMemory() override; void enumerateComputer () override; void enumerateNics() override; + void enumerateGraphicsApis() override; }; } // namespace platform diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 34cac90a05..35fb92a086 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -264,7 +264,19 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) { } auto rootContext = engine->rootContext(); - rootContext->setContextProperty("GL", ::getGLContextData()); + + static QJsonObject QML_GL_INFO; + static std::once_flag once_gl_info; + std::call_once(once_gl_info, [] { + const auto& contextInfo = gl::ContextInfo::get(); + QML_GL_INFO = QJsonObject { + { "version", contextInfo.version.c_str() }, + { "sl_version", contextInfo.shadingLanguageVersion.c_str() }, + { "vendor", contextInfo.vendor.c_str() }, + { "renderer", contextInfo.renderer.c_str() }, + }; + }); + rootContext->setContextProperty("GL", QML_GL_INFO); rootContext->setContextProperty("urlHandler", new UrlHandler(rootContext)); rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath())); rootContext->setContextProperty("ApplicationInterface", qApp);