- Qt/OpenGL: drawing into non-exposed windows
- 1 Answer 1
- Not launching on windows 10 x64 #33
- Comments
- lashmanov commented Jun 22, 2016
- mkae commented Jun 22, 2016 •
- KimuraRyo commented Jun 23, 2016
- lashmanov commented Jun 23, 2016
- GetMessage() while the thread is blocked in SwapBuffers()
- Swapbuffers called with non exposed windows
- Swapbuffers called with non exposed windows
Qt/OpenGL: drawing into non-exposed windows
I am using gitlab-ci-runner to automatically test a desktop Qt/OpenGL application on every commit. On Windows 8, the application is executed by a system service installed with gitlab-ci-runner, hence it is run «hidden», i.e. on no visible desktop. All the UI modules initialize and run anyway, except the OpenGL module, which never gets an «expose» event; if I try to draw into the OpenGL context without the window being exposed I get the error:
I have found out that it is rather difficult and not recommended to execute a Windows GUI application from a service on a running desktop session (see How can a Windows service execute a GUI application?).
Now, I don’t need the user to see the application, I just need the OpenGL part to work correctly. Is there a way I can «pretend» to expose a window somehow, or is there any other way to get this to run correctly from a system service?
1 Answer 1
Is there a way I can «pretend» to expose a window somehow, or is there any other way to get this to run correctly from a system service?
Two problems you’re running into:
If a window is not exposed all pixels rendered to will fail the pixel ownership test and rendering turns into a NoOp for all the pixels. The workaround for that is using wither a PBuffer or (recommended) a framebuffer object. Neither will immediately work with a on screen window, so you’ll have to change some code.
In Windows processes started as a service usually don’t get access to the graphics hardware, so you’re limited to the capabilities of the software GDI OpenGL fallback (limited to OpenGL-1.1, hence no support for FBOs or PBuffers).
If you need GPU acceleration you can either invest into some grid computing GPU hardware (well, actually every GPU could do it, but the drivers disallow it for consumer grade stuff) to get a working OpenGL accelerated context. Or you can migrate to Linux, use a GPU supported by KMS/DRI/DRM and completely circumvent any graphics system. There’s no official guide on how to do that, but it’s on my (lengthy) ToDo list writing such a tutorial.
If you can live without GPU acceleration, drop a Windows build of Mesa with the softpipe renderer beside your program’s .exe ; the Windows Mesa softpipe build comes as a opengl32.dll fully API and ABI compatible with the standard opengl32.dll , but is independent of any graphics driver. It gives you OpenGL-3.3 support including FBOs and PBuffers.
Not launching on windows 10 x64 #33
Comments
lashmanov commented Jun 22, 2016
I can not run BSDFProcessor.exe on my win 10 home x64.
exe doesn’t show anything? in task manager it appears, and then just crash without any word
The text was updated successfully, but these errors were encountered:
mkae commented Jun 22, 2016 •
Can you try building it yourself, perhaps?
Did you run it from a CMD window in order to see some error output? If you see something, please attach it to this issue.
KimuraRyo commented Jun 23, 2016
I’m developing BSDF Processor on Windows 10 Home x64 without problems.
Any message isn’t shown if it is run on a Windows 10 console. I have uploaded BSDF Processor with a console to see log messages.
BSDFProcessor-1.1.4-windows-x86_console.zip
Following messages are displayed on my end, when the main window is shown.
lashmanov commented Jun 23, 2016
Theris no envy output in console in my case, I’l try tu build and report
what’s happening.
четверг, 23 июня 2016 г. пользователь KIMURA Ryo написал:
I’m developing BSDF Processor on Windows 10 Home x64 without problems.
Any message isn’t shown if it is run on a Windows 10 console. I have
uploaded BSDF Processor with a console to see log messages.
BSDFProcessor-1.1.4-windows-x86_console.zip
https://raw.githubusercontent.com/wiki/KimuraRyo/BSDFProcessor/binaries/BSDFProcessor-1.1.4-windows-x86_console.zip
Following messages are displayed on my end, when the main window is shown.
[Integrator::Integrator] numSampling_: 50000
GL_VENDOR: NVIDIA Corporation
GL_RENDERER: GeForce GTX 750 Ti/PCIe/SSE2
GL_VERSION: 4.5.0 NVIDIA 368.39
GL_SHADING_LANGUAGE_VERSION: 4.50 NVIDIA
GL_VENDOR: NVIDIA Corporation
GL_RENDERER: GeForce GTX 750 Ti/PCIe/SSE2
GL_VERSION: 4.5.0 NVIDIA 368.39
GL_SHADING_LANGUAGE_VERSION: 4.50 NVIDIA
libbsdf-0.9.3
OpenSceneGraph-3.4.0
Qt-5.6.0
Eigen-3.2.8
QOpenGLContext::swapBuffers() called with non-exposed window, behavior is undefined
QOpenGLContext::swapBuffers() called with non-exposed window, behavior is undefined
QOpenGLContext::swapBuffers() called with non-exposed window, behavior is undefined
GetMessage() while the thread is blocked in SwapBuffers()
Vsync blocks SwapBuffers(), which is what I want. My problem is that, since input messages go to the same thread that owns the window, any messages that come in while SwapBuffers() is blocked won’t be processed immediately, but only after the vsync triggers the buffer swap and SwapBuffers() returns. So I have all my compute threads sitting idle instead of processing the scene for rendering in the next frame using the most recent input. I’m particularly concerned with having very low latency. I need some way to access all pending input messages to the window from other threads.
Windows API provides a way to wait for either Windows events or input messages using MsgWaitForMultipleObjects(), yet there’s no similar way to wait for a buffer swap together with other things. That’s very unfortunate.
I considered calling SwapBuffers() in another thread, but that requires glFinish() to be called in the window’s thread before signalling another thread to SwapBuffers(), and glFinish() is still a blocking call so it’s not a good solution.
I considered hooking, but that also looks like a dead end. Hooking with WH_GETMESSAGE will have the GetMsgProc() be called not asynchronously, but when the window’s thread calls GetMessage()/PeekMessage(), so it’s no help. Installing a global hook doesn’t help me either due to the need of calling RegisterTouchWindow() with a specific window handle to process WM_TOUCH — and my input is touch. And, while for mouse and keyboard, you can install low level hooks that capture messages as they’re posted to the thread’s queue, rather than when the thread calls GetMessage()/PeekMessage(), there appears to be no similar option for touch.
I also looked at wglDelayBeforeSwapNV(), but I don’t see what’s preventing the OS from preempting a thread sometimes after the call to that function but before SwapBuffers(), causing a miss of the next vsync signal.
So what’s a good workaround? Can I make a second, invisible window, that will somehow be always the active one and so get all input messages, while the visible one is displaying the rendering? According to another discussion, message-only windows (CreateWindow with HWND_MESSAGE) are not compatible with WM_TOUCH. Is there perhaps some undocumented event that SwapBuffers() is internally waiting on that I could access and feed to MsgWaitForMultipleObjects()? My target is a fixed platform (Windows 8.1 64-bit) so I’m fine with using undocumented functionality, should it exist. I do want to avoid writing my own touchscreen driver, however.
Swapbuffers called with non exposed windows
Vaz007 |
| ||||||||||||||||||||||||
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.
[ Время генерации скрипта: 0.1144 ] [ Использовано запросов: 21 ] [ GZIP включён ] Swapbuffers called with non exposed windows
|