Get OpenGL (WGL) context from QOpenGLContext - opengl

I'm trying to get the OpenGL context (HGLRC) from the QQuickView window.
I need to pass it to a non-Qt library. I can get a QOpenGLContext easily enough:
m_qtContext = QOpenGLContext::currentContext();
How do you obtain the OpenGL context from the Qt class? (QOpenGLContext)

There's not exactly a public API for this, as far as I know. Note that Qt 5 removed most of the native handles from the APIs. This should do the trick:
QPlatformNativeInterface *iface = QGuiApplication::platformNativeInterface();
HGLRC ctx = (HGLRC)iface->nativeResourceForContext("renderingContext", context);
(not sure about the last cast, but that looks correct according to the relevant source).

You can get the current OpenGL context from WGL in any framework if you call wglGetCurrentContext (...) while your thread has the context bound. Keep in mind that frameworks will usually change the current context whenever they invoke a window's draw callback / event handler, and may even set it to NULL after completing the callback.
WGL has a strict one-to-one mapping for contexts and threads, so in a single-threaded application that renders to multiple windows you will probably have to call this function in a window's draw callback / event handler to get the proper handle.
In simplest terms, any time you have a valid context in which to issue GL commands under Win32, you can get a handle to that particular context by calling wglGetCurrentContext (...).
If your framework has a portable way of acquiring a native handle, then by all means use it. But that is definitely not your only option on Microsoft Windows.

Related

Do I need to call SDL_GL_DeleteContext before SDL_DestroyWindow?

In SDL if I destroy a window anyway, do I need to delete the OpenGL context beforehand or does it delete it automatically? I don't want a memory leak.
Also when do I need to call SDL_GL_MakeCurrent? Is this only required if I have multiple windows with a GLcontext each?
Couldn't find anything in the documentation.
Well I call
SDL_GL_DeleteContext
SDL_DestroyWindow
SDL_QuitSubSystem
in that order. I once read the documentation very carefully and I remember vaguely that somewhere in the documentation this was mentioned. Although I have to warn that I read the one for SDL2. However this should be the same in SDL1.
Because all that SDL internals are easy to forget, I wrote a nice C++ wrapper:
https://github.com/Superlokkus/CG1/blob/master/src/sdl2_opengl_helper.cpp#L68
SDL doesn't delete the contexts automatically, you should do it manually.
Usually, my call stack goes like:
SDL_GL_DeleteContext(m_context);
SDL_DestroyWindow(m_window);
SDL_Quit();
Keeping track of the pointer shouldn't be that much of an issue either, since you could wrap the window system in a simple class/struct and just pass that around, like so:
class Window
{
public:
SDL_Window* window;
SDL_GLContext context;
};
As for your second question, each context you make is tied to the corresponding SDL window you specify when making the context current. Selecting/Making another context current and rendering on that context will draw on the window and context you make current.
You need to call SDL_GL_MakeCurrent once you make the window to be able to use it. When making multiple windows, make the context you want current and that will be rendered to. You should also use MakeCurrent if you're wanting to access OpenGL resources in another thread - but keep in mind that a context can only be active in ONE thread at a time, and you will have to recall the function in your main thread upon next use.

How to obtain and interact with QWidgets from QProcess

I have Application A which is a third party Windows application (with GUI) that uses the Qt library.
I want to write Application B which will be responsible for starting Application A. I want Application B to also find buttons on Application B (QWidgets) and send them mouse inputs (click, double click etc).
I can run Application A through using the start function on a QProcess.
How do I do the following from my instance of the QProcess:
Get the top level window(s) for the process
Get a widget by name or (other identifiable attribute)
Get the widgets caption, colour and coordinates (and maybe some other data)
Send mouse move and click events to specific coordinates
Give a widget keyboard focus
Send keyboard key presses
Note - I know how to do this with the Windows API, but asking for a way via Qt. The specific Application A in question does not use the native windowing system, therefore window handles will not show up in Spy++ or Windows API functions.
Update 1 - Cannot seem to get any meaningful objects through the process's children
My attempt at getting child widgets for the process:
QProcess* process = new QProcess();
QString program = "\"C:\\Program Files (x86)\\foo\\bar.exe\"";
process->start(program);
auto widgets = process->findChildren<QWidget*>("", Qt::FindChildrenRecursively);
auto i = widgets.count();
// i = 0
If I find children of type <QObject*> I get 4 results. I used metaObject()->className() to see that I have two pairs of QWindowsPipeReader and QWinOverlappedIoNotifier objects.
Update 2 - Cannot create/inject window from another process
I noticed that when I run the QProcess I can use Windows API functions to get the top level window (top level only). I read in the Qt documentation that you can create a QWindow from the handle of a window in another process using QWindow::fromWinId.
Using this function will throw an 0xC0000005: Access violation reading location 0x00000000. error. I am not passing in a null handle. I am using reinterpret_cast to get the HWND to a WId type. It creates a QWindow only when I create a QApplication beforehand.
The new QWindow will have no children (using window->findChildren<QObject*>("", Qt::FindChildrenRecursively); I assume that the creation of the QWindow does not bring across associated child widgets.
Update 3 - I am currently reading into whether inter-process communication can be used
I have come across various threads, questions and code snippets regarding ICP in Qt. I don't see anything so far that specifically shows that ICP is possible when one of the processes is third party.
I have seen that the Squish Gui test tool lets you interrogate QWidget properties.
This will never work the way you intend it to.
If you really wish to take direct control over the other application, you must inject your code into that application. Let's assume that the application uses a dynamically linked Qt. Then:
Build a binary-compatible version of Qt, using the same compiler that was used to build the application you intend to tweak.
Replace the application's Qt with yours. Everything should still work fine, given that yours should be binary compatible. If not, the binary compatibility isn't there, and you must tweak things until they work.
Edit your Qt to add a hook to initialize your code at the end of QApplication constructor. This makes the Qt module that provides QApplication dependent on your code.
Put your code into a dll that the widgets (for Qt 5) or gui (for Qt 4) module is now dependent on.
Again replace the app's Qt with yours, with hooks that start your code.
Your code will of course need to be asynchronous, and will be monitoring the application's progress by inspecting the qApp->activeWindow(), qApp->allWidgets(), etc.
That's pretty much the only way to do it. You can of course inject your code in any other way you desire, but you will need to work with a binary-compatible version of Qt just to compile your code. Note that binary compatibility encompasses more than merely using the same compiler version and Qt version. Many of the configure switches must be the same, too.

QT Managing OpenGL context in a separate thread

I have learned about setting up separate rendering thread for Qt QGLWidget here ,here and here .
I also managed to get a kind of "working" setup: clearing color in the viewport.Seems to be ok.But I am getting the following warning:
QOpenGLContext::swapBuffers() called with non-exposed window, behavior
is undefined
I first create a widget that inherits from QGLWidget.Where I also setup OpenGL Format:
In the Widget constructor:
QGLFormat format;
format.setProfile(QGLFormat::CompatibilityProfile);
format.setVersion(4,3);
format.setDoubleBuffer(true);
format.setSwapInterval(1);
setFormat(format);
setAutoBufferSwap(false);
Then I init the rendering thread in the same Widget:
void GLThreadedWidget::initRenderThread(void){
doneCurrent();
context()->moveToThread(&m_renderThread);
m_renderThread.start();
}
and from that point the whole rendering is done inside that thread:
RenderThread constructor:
RenderThread::RenderThread(GLThreadedWidget *parent)
:QThread(),glWidget(parent)
{
doRendering = true;
}
RenderThread run() method:
void RenderThread::run(){
glWidget->makeCurrent();
GLenum err = glewInit();
if (GLEW_OK != err) {
printf("GLEW error: %s\n", glewGetErrorString(err));
} else {
printf("Glew loaded; using version %s\n", glewGetString(GLEW_VERSION));
}
glInit();
while (doRendering){
glWidget->makeCurrent();
glClear(GL_COLOR_BUFFER_BIT );
paintGL(); // render actual frame
glWidget->swapBuffers();
glWidget->doneCurrent();
msleep(16);
}
}
Anyone can point out where is the issue?And if that message can be discarded? Also a straightforward and concise explanation on render thread setup in Qt would be extremely helpful.Using Qt 5.2 (Desktop OpenGL build)
With what you've shown, it looks like that message handler warning you were getting was because you started triggering buffer swaps "too soon" in the window setup sequence, either directly through QGLContext::/QOpenGLContext::swapBuffers() or indirectly through a number of possible ways, none of which are really detectable outside of manual debugging. What I mean by too soon is before the widget's parent window was marked "exposed" (before it was being displayed by the windowing system).
As far as whether the message can be discarded, it can...but it's not safe to do, as in it's possible to get undefined behavior for the 1st few frames or so where you do it and the window's not ready (especially if you're immediately resizing to different extents at startup than your .ui file specifies). Qt documentation says that before your window's exposed, Qt has to basically tell OpenGL to paint according to what are effectively non-trustworthy extents. I'm not sure that's all that can happen though personally.
With the code you showed, there's an easy fix--avoid even starting your render logic until your window says it's exposed. Detecting exposure using QGLWidget isn't obvious though. Here's an example roughly like what I use, assuming your subclass from QGLWidget was something like 'OGLRocksWidget', it was a child of a central widget, and that central widget was a child of your implementation of QMainWindow (so that your widget would have to call parentWidget()->parentWidget() to get at its QMainWindow):
OGLRocksWidget::paintGL()
{
QMainWindow *window_ptr =
dynamic_cast<QMainWindow *>(parentWidget() ? parentWidget()->parentWidget() : 0);
QWindow *qwindow_ptr = (window_ptr ? window_ptr->windowHandle() : 0);
if (qwindow_ptr && qwindow_ptr->isExposed())
{
// don't start rendering until you can get in here, just return...
// probably even better to make sure QGLWidget::isVisible() too
}
}
Of course you don't have to do this in your implementation of QGLWidget::paintGL(), but in your particular setup you're better off not even starting your render thread until your window tells you it's exposed.
It looks like you have might have slightly bigger problems than that though. You weren't hooking the right GL activity into the right places in your code vs QGLWidget's intent. I feel for the position you were in because the documentation on this is a little spotty and scattered. For that part, QGLWidget's detailed description down where it says "Here is a rough outline of how a QGLWidget subclass might look" is a good place to start getting the idea. You'll want to override any of the key virtuals in there that you have related code for and move them into those calls.
So for example, your widget's constructor is doing setup work that is probably safer to put in an initializeGL() override, since QGLWidget's intent is to signal you when it's safely time to do that through that call. What I mean by safer whenever I say that here is that you won't get seemingly random debug exceptions (that in release builds can silently wreak havok on your runtime stability).
Side advice: install Qt source, point your debugger at it, and watch your code run, including into Qt. Your setFormat() call, last time I watched it, actually deletes the current underlying QOpenGLContext. That's probably good to know because you'll want to create a new one soon after or at least test out your options.
The risk of instability is why I'm trying to put together at least some kind of answer here a year later. I just learned this through a lot (too much) debugging. I love what the Qt team's done with it, but Qt will be much better off when they finish migrating everything over to QOpenGL* calls (or wherever they see a final proper place for their OpenGL support including permanent considerations for it and windowing support together).
A QOpenglWidget comes with its own context. If you want a background thread to do the rendering, you have to pass a shared context to the thread and do a few steps correct.
Details in: https://stackoverflow.com/a/50368372/3082081

2 threads - one with opengl window and the second with wxwidgets one

I'm writing an editor and I have a problem which means calling native file save/open dialog from my opengl app. The editor is written with my in-game opengl gui. So i came up with idea that when user press "load" or "save", I will create a thread which will create required (non-visible) wx window and it will call wxFileDialog and after the job is done I will delete that thread. Is it possible or maybe there are better aproaches to acces file open/save dialog in cross platform way from an opengl app?
wxWidget has a OpenGL widget. Put your OpenGL stuff into this one, forward the event received by the widget to your GUI system, then you'll not have to battle for the event loop.
As others have already said, the simplest solution is to use wxWidgets for the main loop and wxGLCanvas for OpenGL stuff.
But if this is impossible, for some reason, you should indeed be able to use wxWidgets from another thread. Just remember that wxWidgets GUI functionality can only be used from a single thread so you need to initialize it from that thread too. And, of course, you'll need to handle thread synchronization yourself as wxWidgets won't know anything about the rest of your program.
If you are using GLUT, or equivalent, then you do NOT have a cross-platform framework. If you want a cross-platform app, then your will have to choose a framework ( e.g wxWidgets or Qt or whatever ) and proceed from there. Otherwise, you can use the native calls to the windows API if you are on windows, and the equivalent on other platforms.
GLUT only gives you a console style application. If you want a GUI, then you have to choose a GUI framework, even if you do not want cross-platform. There as many to choose from, the choice mostly depends on which you are most familiar with. Then you add the calls to the OpenGL library from you GUI application, however built. This way, you do not have to muck around with multiple threads.
It may be that you have a massive investment in your GLUT application, and do not wish to discard it merely to get a few GUI capabilities. In this case, I recommend building a new GUI app, separate from your GLUT application, which communicates with your existing app using a socket ( or other interprocess com system ) but runs in a separate process. This way you will not encounter all the ghastly, hard to fix bugs, created by multithreaded apps.

Windowless OpenGL

I would like to have a windowless OpenGL context (on both GNU/linux with Xorg and Windows). I'm not going to render anything but only call functions like glGetString, glCompileShader and similar.
I've done some goggling but not come up with anything useful, except creating a hidden window; which seems like a hack to me.
So does anyone have a better idea (for any platform)?
EDIT: With Xorg I was able to create and attach an OpenGL context to the root-window:
#include<stdio.h>
#include<stdlib.h>
#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
int main(int argc, const char* argv[]){
Display *dpy;
Window root;
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo *vi;
GLXContext glc;
dpy = XOpenDisplay(NULL);
if ( !dpy ) {
printf("\n\tcannot connect to X server\n\n");
exit(0);
}
root = DefaultRootWindow(dpy);
vi = glXChooseVisual(dpy, 0, att);
if (!vi) {
printf("\n\tno appropriate visual found\n\n");
exit(0);
}
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
glXMakeCurrent(dpy, root, glc);
printf("vendor: %s\n", (const char*)glGetString(GL_VENDOR));
return 0;
}
EDIT2: I've written a short article about windowless opengl (with sample code) based on the accepted answer.
Actually, it is necessary to have a window handle to create a "traditional" rendering context (the root window on X11 or the desktop window on Windows are good for this). It is used to fetch OpenGL information and extentions availability.
Once you got that information, you can destroy the render context and release the "dummy" window!
You should test for the extensions ARB_extensions_string and ARB_create_context_profile, (described in these page: ARB_create_context). Then, you can create a render context by calling CreateContextAttribs, in a platform independent way, without having a system window associated and requiring only the system device context:
int[] mContextAttrib = new int[] {
Wgl.CONTEXT_MAJOR_VERSION, REQUIRED_OGL_VERSION_MAJOR,
Wgl.CONTEXT_MINOR_VERSION, REQUIRED_OGL_VERSION_MINOR,
Wgl.CONTEXT_PROFILE_MASK, (int)(Wgl.CONTEXT_CORE_PROFILE_BIT),
Wgl.CONTEXT_FLAGS, (int)(Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT),
0
};
if ((mRenderContext = Wgl.CreateContextAttribs(mDeviceContext, pSharedContext, mContextAttrib)) == IntPtr.Zero)
throw new Exception("unable to create context");
Then, you could associate a frame buffer object or a system window to the created render context, if you wish to render (but as I understand, you want to compile only shaders).
Using CreateContextAttribs has many advantages:
It is platform independent
It's possible to request specific OpenGL implementation
It's possible to request a > 3.2 OpenGL implementation
It's possible to force the forward compatibility option (shader only rendering, that's the future way)
It's possible to select (in a forward compatible context only) a specific OpenGL implementation profile (actually there is only the CORE profile, but there could be more in the future.
It's possible to enable a debugging option, even if it isn't defined how this option could be used by the actual driver implementation
However, older hardware/drivers could not implements this extension, indeed I suggest to write a fallback code in order to create a backward compatible context.
Until you create a window, OpenGL has no idea what implementation you use. For example, there's a very different driver (and different hardware acceleration) for OpenGL in a remote X-Windows session vs OpenGL in an DRI X-Windows session. Shader language support might be different between these cases, and the output of the shader compiler is definitely going to be implementation-dependent, as well as any errors generated based on resource exhaustion.
So while actually creating a window may not be 100% necessary, you have to associate your context with the graphics hardware (or lack thereof) somehow, and since this can be done with a window no one bothered implementing an alternate method.
You need a window to host the context and you need a context to be able to do anything.
Source
If you don't want to display anything make the window invisible.
If there was another way to do this, it would be documented somewhere and easily found as it's not an uncommon problem.
One of the things I have done - which is admittedly a bit of a hack - to avoid the overhead of creating my own GL window - is to leverage open process windows.
The key to understanding OpenGL is this: All you needs to create a GL context with the call to wglCreateContext is a valid DC.
There's NOTHING in the documentation which says it has to be one you own.
For testing this out, I popped up Worlds Of Warcraft, and leveraging SPY++ to obtain a window handle, I then manually plugged that handle into a call to GetDC, which returns a valid Device Context, and from there, I ran the rest of my GL code like normal.
No GL window creation of my own.
Here's what happened when I did this with both Worlds of Warcraft and Star Trek Online https://universalbri.wordpress.com/2015/06/05/experiment-results
So to answer your question, YES you do need a window, but there's nothing in the documentation which states that window needs to be owned by you.
Now be advised: I couldn't get this method to provide valid visual output using the desktop window, but I was able to successfully create a DC using getDeskTopWindow API for the HWND and then a call to GetDC. So if there's non visual processing you want to use OpenGL for - let me know what you're doing, i am curious, and if you DO happen to get the GetDesktopWindow method working with the visuals - PLEASE repost on this thread what you did.
Good luck.
And don't let anyone tell you it can't be done.
When there's a will there's a way.
With GLFW, you can do this by setting a single <VISIBLE: FALSE> window hint