Windowless OpenGL - c++

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

Related

How should a Windows application with custom controls be drawn with Direct2D?

I would like to create a Windows application (for Windows 10) using the C++ and the Windows API. I already have some basic knowledge of using the built-in windows controls to create a basic application, but would now like to expand into custom controls . Since I have no need for my application to be compatible with anything but Windows 10, and would like to use a reliable API which supports transparency and anti-aliasing but is also fast enough to render a GUI, I have chosen to use Direct2D.
The MSDN documentation says:
'Your application should create render targets once'
Bearing this in mind, should each child window use one ID2D1HwndRenderTarget which renders only to the parent window (and doesn't respond to the child windows' WM_PAINT messages), or should there be a single ID2D1DCRenderTarget which would draw to each control using the device context from the WM_PAINT message (using bindDC() - although I would still like to be able to use transparency, and am not interested in GDI interoperability)? Should I even be using Direct2D at all?
I would like to use the Windows API, so a solution involving QT or MFC wouldn't work. I haven't got a specific application in mind, but would eventually like to create a simple library that would enable me to quickly produce GUI applications that have a custom look.
I have spent hours scouring the web for answers, but have found nothing conclusive. MSDN itself seems particularly unhelpful, it just teaches you to draw an ellipse and stops there. Please forgive me if I have accidentally broken the rules of asking questions - as you can probably tell I am new to Stack Overflow - and if any other information is needed, I will of course include it (I am using C++ with Visual Studio Community 2019).

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 manipulate application windows on linux with C/C++

I dont have a lot of experience with C so sorry if this is a dumb question.
I'm writing an application that will monitor and manipulate application windows and i need to figure out how to do the following:
Get a list of all application windows
Be notified when a window is resized
Be notified when the a user maximises/minimises a window
Set the size and position of an application window.
I spent quite a while searching google but did not find anything useful. The language is not to important as i could make this project work with C or C++ maybe even C#
Any help would be appreciated.
on linux windows are handled by X11 ( X Window System https://en.wikipedia.org/wiki/X_Window_System, https://en.wikipedia.org/wiki/X.Org_Server ) and X Window Managers like Enlightenment ( https://en.wikipedia.org/wiki/Comparison_of_X_window_managers ), and tools and libraries like xdotool or Xlib ( https://www.lemoda.net/c/xlib-resize/ ...).
X11 is low(est)-level application window handling on linux
on this X11 basis you normally write programs that contain windows using Qt or GTK+ framework, in both frameworks are implemented methods to do all your mentioned tasks ( What should I choose: GTK+ or Qt? )
important is the installed X windows manager ( https://en.wikipedia.org/wiki/Comparison_of_X_window_managers ). In the overlying Qt and GTK+ frameworks only functions can be used that are implemented by the underlying X window manager
resize window event capturing in Qt and GTK :
http://www.qtcentre.org/threads/54968-how-to-detect-window-resize-event
GTK detecting window resize from the user
A list of all open X windows can be queried with XQueryTree function from the Xlib library
( How to get the list of open windows from xserver )
xwininfo ( https://linux.die.net/man/1/xwininfo ) can be used to collect information about open windows
EDIT: I was just thinking of something else when I answered the question the first time. In fact what you are asking for is pretty simple.
Here is a potential solution.
Register for Create/Destroy/Resize window events (XCB_EVENT_MASK_STRUCTURE_NOTIFY) so you can keep up with newly added/destroyed/resized windows. Depending on your setup you may want to add the XCB_EVENT_MASK_PROPERTY_CHANGE so you can tell if the "minimized" or "maximized" property is set.
Query _NET_CLIENT_LIST (ie via xcb_ewmh_get_client_list) or use
XQueryTree to get all (application) windows. The former will give you a filtered list that will probably be a superset of "application windows". The latter will give you every single window which will probably be more than what you want.
Send configure request to resize the window. Like others have said, xdotool can be used to send these requests. Note that, in general, these requests are likely to be blocked/modified by the WM. If you don't own the window, there is no good way around this unless your WM allows it. If you do own the window, you could set the override redirect field on the window.
Below is a code sample on how you might listen for events (complied with -lxcb). Note that this is just a sample and you would probably want to filter events in the switch statement (ie you don't want all properties)
void main(){
//create connection using default display
xcb_connection_t* dis = xcb_connect(NULL, NULL);
if(xcb_connection_has_error(dis))
exit(1);
xcb_screen_t*screen=xcb_setup_roots_iterator(xcb_get_setup(dis)).data;
int root = screen->root;
int mask = XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE;
if(xcb_request_check(dis,xcb_change_window_attributes_checked(dis, root,XCB_CW_EVENT_MASK, &mask)))
exit(1);//an error occured
while(1){
xcb_generic_event_t *event;
event = xcb_wait_for_event(dis);
switch(event->response_type){
case XCB_CREATE_NOTIFY:
printf("New window\n");
break;
case XCB_DESTROY_NOTIFY:
printf("Window deleted\n");
break;
case XCB_PROPERTY_NOTIFY:
printf("Window property change\n");
break;
case XCB_CONFIGURE_NOTIFY:
printf("Window size has changed\n");
break;
}
}
}
If you are new to X11, I personally recommend xcb instead of Xlib because its easier to debug, but its just a personal preference. You could use either or both. Also keep in mind that X11 api has been ported to many languages like python so you are not stuck with C.
Looking through your comments, yes DE/WM can impact your code. Not sure of your use case or how deep you want to go but you can
switch WM (there are a lot to choose from)
Run in a sandbox where no WM is running
See if your WM can white list certain windows so you can modify them directly or see if you WM is scriptable/allows you to add hooks when certain events are run
Write your own WM. You can get notified of every event you care about but you'd have to do everything else you'd ever want so it would be a lot of work
I will admit that X programming can have a bit of a learning curve but it gets better.

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

Get OpenGL (WGL) context from QOpenGLContext

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.