How to create a QOpenGLContext from a GLFW EGL window?
-
I wanted to embed a QML scene into a GLFW window using QQuickRenderControl. From what I can see, one of the first steps is to get the OpenGL context from GLFW, and this is where I run into an issue. My code crashes on the line: QOpenGLContext *glfwQtContext = QNativeInterface::QEGLContext::fromNative(eglContext, eGLDisplay);. Am I doing something wrong? Configuration: Qt 6.9, Ubuntu 24.04 Wayland, GLFW 3.4.
#include <QGuiApplication> #include <QCoreApplication> #include <QOpenGLContext> #include <QOffscreenSurface> //#define GLFW_EXPOSE_NATIVE_WAYLAND #define GLFW_EXPOSE_NATIVE_EGL #include <GLFW/glfw3.h> #include <GLFW/glfw3native.h> #include <iostream> int main(int argc, char *argv[]) { //qputenv("QT_QPA_PLATFORM","eglfs"); qputenv("QT_QPA_PLATFORM","wayland"); QGuiApplication app(argc, argv); if(!glfwInit()){ std::cerr << "Failed initialize glfw"; exit(1); } glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow(800, 600, "Qml in GLFW window", nullptr, nullptr); if(!window){ std::cout << "Wndow creation failed!"; exit(EXIT_FAILURE); }else{ std::cout << "Sucessful window creation!" << std::endl; } glfwMakeContextCurrent(window); EGLContext eglContext = glfwGetEGLContext(window); EGLDisplay eGLDisplay = glfwGetEGLDisplay(); QOpenGLContext *glfwQtContext = QNativeInterface::QEGLContext::fromNative(eglContext, eGLDisplay); glfwQtContext->create(); if(!glfwQtContext){ std::cout << "[ERROR] Failded to create QOpenGLContext from glfw context !!" << std::endl; exit(EXIT_FAILURE); }else{ std::cout << "[SUCCESS] Successfull create QOpenGLContext from glfw context !!" << std::endl; } return 0; }Additionally, I tried doing something similar with GLX, and it seems that the context is created successfully—the program doesn't crash, though I haven't tried rendering yet, as I am much more interested in the EGL version.
#include <QGuiApplication> #include <QCoreApplication> #include <QOpenGLContext> #include <QOffscreenSurface> #define GLFW_EXPOSE_NATIVE_GLX #include <GLFW/glfw3.h> #include <GLFW/glfw3native.h> #include <iostream> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); if(!glfwInit()){ std::cerr << "Failed initialize glfw"; exit(1); } glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow(800, 600, "Qml in GLFW window", nullptr, nullptr); if(!window){ std::cout << "Wndow creation failed!"; exit(EXIT_FAILURE); }else{ std::cout << "Sucessful window creation!" << std::endl; } glfwMakeContextCurrent(window); GLXContext glxContext = glfwGetGLXContext(window); QOpenGLContext *glfwQtContext = QNativeInterface::QGLXContext::fromNative(glxContext); glfwQtContext->create(); if(!glfwQtContext){ std::cout << "[ERROR] Failded to create QOpenGLContext from glfw context !!" << std::endl; exit(EXIT_FAILURE); }else{ std::cout << "[SUCCESS] Successfull create QOpenGLContext from glfw context !!" << std::endl; } QOffscreenSurface surface; glfwQtContext->makeCurrent(&surface); return 0; } -
Very suspicious code, your first example with GLTF, do you actually have an EGL based context? If you do, are the implementations the same? it's possible that both Qt and GLFW try to load their own EGL and GL ES libraries. Kkeep in mind that its possible to create an ES context without using EGL, so you're looking for an ES context and assuming that it was created via EGL that might a false assumption.
In general In my opinion this approach is just too finicky and is not going to work, whenever you have 2 different things that are using the same OpenGL context you're going to run into issues with a) unexpected state changes b) context version mismatch. A much better approach (and the only thing that actually has any chance of working) is to setup a context sharing group and share a render target texture. I.e. you create a shareable texture, setup an FBO, let QML render into the texture and the use that texture to render the result on the GLFW side.