i wan't to use Native OpenGL in the paint function of my widgets(QPainter), to improve performance.
i saw that there is function QPainter::begin/endNativePainting(), that can help me.
but i can't find examples for that...
i wanted to know if those functions are low cost, or evry use of them reduce performance?
2.can i define beginNativePainting() and endNativePainting(), in general for all the widgets i use, instead of using that in every paint function i have.
tnx for any help....
There is some basic example code right in the documentation: http://doc.qt.io/qt-4.8/qpainter.html#beginNativePainting
The functions themselves should be fairly low-cost, but calling them might still cause a noticeably overhead, because Qt has to flush its internal painting queue on the beginNativePainting() call and probably has to assume that everything is changed as soon as endNativePainting() is called.
For the second part I am not sure if I understand what you are aiming at. Basically if you have a QPainter object, you can call beginNativePainting() once. But you have to match it with an endNativePainting() call. So the usual place would be the paint() method.
Qt is using a range of OpenGL functionalities to implement its 2D painting, including custom shaders and various frame buffers. It puts OpenGL into a pretty messy state.
beginNativePainting / endNativePainting are there to allow Qt's drawing engine to save this context and retrieve it once the user is done drawing.
It would have been nice to have the xxxNativePainting methods do the contrary (i.e. automatically save and restore user configuration of OpenGL), but since Qt allows to call OpenGL primitives directly, saving the global state is nigh impossible without tons of code and potential serious performance hit.
Instead, these methods simply save Qt's internal OpenGL state and, rather than having user code start in a configuration that would be meaningless anyway (and likely to change with each new Qt release), reset OpenGL to a "neutral" state.
It means that, inside a begin/end section, you will start with a clean slate: no shader linked, no vertex array, most of global parameters reset, etc.
Contrary to a simple QGLWidget / PaintGL scenario where you can afford to setup the global OpenGL state once and for all and simply call the rendering primitives each frame, you will have to restore pretty much everything just after the call to beginNativePainting (link/bind your shaders, set global parameters, select and enable various buffers, etc).
It also means that you should use native painting sparringly. Having each single widget do custom painting might soon bring your rendering to its knees.
Related
I am trying to use an external to Qt OpenGL context using a window handle that comes from Qt. The setup is:
A QMainWindow - contains various widgets including a QWebEngineView to make some web content available (in my case it's Leaflet for render and interact with OpenStreetMaps tiles)
Panda3D engine - rendered on top of my Qt application using a window handle of the central QWidget.
The setup works...when Panda3D is set to DirectX9 (aka pandadx9). When I switch the pipeline to OpenGL (aka pandagl) I get a black screen (Panda3D's window) and a very glitch OpenGL content (Qt). The reason is simple yet beyond my ability to fix it - QWebEngineView uses OpenGL. Somehow there is a conflict on a OpenGL context level between the engine and Qt. I am looking for a way to resolve this without removing the direct interaction with Panda3D's window (in my case using ShowBase) since the engine already offers a lot in terms of features for handling mouse events that I would otherwise be forced to reimplement in Qt and pass down to the engine. In addition I am not sure if I can make Panda3D render its scene as an FBO and how to load it in a - let's say - QOpenGLWidget. Activating shared OpenGL context before initializing QApplication allows multiple OpenGL widgets to render OpenGL content.
So far I have experimented to integrate Panda3D with Qt in two ways:
run two event loops in parallel - start the Panda3D engine in a child process and then using a pipe communicate with it
run a single event loop - use the event loop of Panda3D engine to also handle the main event loop of Qt by adding a task to the engine's task manager to run QApplication::processEvents() on every cycle
In both cases I am handing over a window Id (QWidget::winId()) as the parent window of Panda3D.
CASE 1 - parallel processes, separated event loops
This resolution comes with a lot of overhead. All the communication between the Qt content (running in the parent process) needs to be sent (via pipe hence involving IPC) to the engine (running in the child process). This adds a lot of code complexity and in case of my logging (using Python's logging module with a custom logging handler that writes records into an SQLite3 database) introduces a whole lot of issues. Concurrent write access to a file between processes is a tricky thing in general and I'm definitely not an expert. This case however does not exhibit the behaviour I'm describing below. In this case however the issue with OpenGL is not present!
CASE 2 - single process, single event loop
In my opinion this is a more elegant and is what I would like to go with (if possible). An example can be found here. I use the engine's main loop to process Qt's main loop. This is due to the fact that a 3D game engine usually would need to deal with far more events for a shorter period of time (processing rendering, audio, video, filesystem access, physics and so on) then a standard Qt GUI. This is also the recommended way as described in the official documentation of the engine. The other way around (Qt's main loop handling Panda3D's) is also possible. Imho neither have anything to do with my issue namely the moment I add anything Qt-ish that uses OpenGL, the problem I've described above occurs. On Windows this is not a huge deal breaker since I can also use DirectX for the engine, while Qt does it's OpenGL thing. On Linux it is not possible (without something like wine). In addition I want to use exclusively OpenGL including GLSL.
Here is a visual representation of case 1 and case 2 (but with mixed DX9 and OpenGL):
And below there are two visual representations of case 2 with only OpenGL:
While Panda3D offers CPU rendering (aka p3tinydisplay), QWebEngineView does not. Falling back to CPU rendering on the engine side is not an option considering the huge amount of polygons I have to render not to mention the fact that I can do something more useful with the CPU (e.g. processing the physics).
Last but not least I have seen a third integration attempt, which I quickly discarded - rendering the scene as an image to RAM, reading it in Qt, generating a QPixmap from it and painting on top of a QLabel. Needless to say this is a no go for my scenario due to the heavy hit on performance among others.
Any ideas how to tackle this?
I don't think event loops have to do with anything here; the problem is that by default child windows get the same device-context (DC) as the parent. In your case that's a problem because two different components (Qt framework, and Panda3D engine) try to ChoosePixelFormat and initialize OpenGL context twice on the same DC, which is not supported.
The proper solution is to create the Panda3D engine QWidget from a QWindow with the Qt::MSWindowsOwnDC style, which corresponds to the CS_OWNDC window-class style. Normally QWidget doesn't create any window at all -- but is rather implemented entirely within the Qt framework by drawing itself on the parent window.
I am not familar with WINAPI, and I am looking for a way to replace WaitForMultipleObjects used in one example I'm porting to Qt by anything using Qt only. Is it possible?
EDIT: (Providing more information as requested in comments)
A 3rd party API provides an array of events:
HANDLE m_hEv[MAX_EV];
In an endles-loop of a thread, the program waits for the events like this:
WaitForMultipleObjects(m_EvMax, m_hEv, FALSE ,INFINITE )
The HANDLE type seems to be void*.
So I wonder, if any Qt class could observe m_hEv for changes and unlock thread execution.
There is no simple way of porting WaitForMultipleObjects outside WinAPI. WinAPI has an "advantage" of that all lockable resources (sockets, files, processes) provide the same generic non-typesafe HANDLE, which is your void*. Unlike other platforms which have different ways of locking and signalling per the type of resource, the event handling in WinAPI is largely independent of the resources. Then a generic function like WaitForMultipleObjects can exist, which doesn't need to care who produced the HANDLEs. So you'll have to understand what the code is trying to do and mimic it differently per scenario.
The biggest difference is in WaitForMultipleObjects third parameter, which is FALSE in your case. Which means that the it will exit waiting as soon as any single event of the waiting array will happen. That is the easier scenario and can be replaced with a QWaitCondition.
Instead of m_hEv, you will pass a QWaitCondition* into the code which signals the event (most probably via WinAPI SetEvent(m_hEv[x]))
Instead of WaitForMultipleObjects, do QWaitCondition::wait().
Instead of SetEvent(), do QWaitCondition::wakeOne().
Would the third parameter be TRUE, then the WinAPI code waits until ALL m_hEv events are signalled. The established name for such functionality is a synchronization barrier and it can be simulated with QEventCondition too, but does not come out of the Qt box. I never needed to do any myself, but SO has some ideas how to do it:
Qt synchronization barrier?
WaitForMultipleObjects is a kind of generic function that works with many things: threads, processes, mutexes, etc. Qt is an OOP library where every class exposes the operations it supports. So the equivalent operation in Qt depends on what class you're using. For example, with threads, use QThread::wait. With mutexes, use QMutex::lock.
I'm porting over a OpenGL application from a win32 project to a Qt project.
In the win32 project I simply had a mainloop that kept executing the next frame as soon as the previous was finished.
In the tutorials I find about Qt and OpenGL, they're using timers to control the update of the scene. However, I'd like to render as many frames as frequent as possible - how to do that?
However, I'd like to render as many frames as frequent as possible - how to do that?
Not with Qt. Qt takes full control of the event loop thus not giving you any means of directly performing idle operations. The standard way to perform idle operations in Qt is to use a QTime with a timeout of 0.
Another possibility was using a second thread just for OpenGL operations. However to work reliably you should create a dedicated OpenGL context for that one thread.
Qt simply is not the right toolkit for those kinds of program where the primary task of the main loop is rendering pictures and input and event management are only secondary.
Try calling update() at the end of your paint handler.
That will queue up another repaint event.
The intrinsic principles of Qt and OpenGL are not about rendering as soon as possible, but it's rendering whenever we want (huge difference).
You have to ask for the system max framerate (search for samples in OpenGL i'm sorry I don't rememember where I saw that). Once you've done that, just create a timer based on this max framerate, so you'll get what you want.
However, I'd like to render as many frames as frequent as possible - how to do that?
Use QTimer with zero interval.
I'm pretty new to QT's graphic view frame, and I couldn't find anything about this in the docs or on Google.
I have a GUI application that draws a representation for some data. The application itself does some work with matrices / vectors (a neural net thing) and has to represent it on a QGraphicsScene. So far so good, but I've noticed that the app segfaults & crashes sooner or later (and usually sooner) if I try to update the QGraphicsScene from another thread. The QT Docs say nothing about thread-safety & Google gives nothing. What I want (and pretty much need) to do is run the calculations & update the GUI representation accordingly, but the GUI controls etc themself have to remain responsive. As I said, my first thought was to do the whole thing in another thread, but it crashes randomly if I try to.
Is there any "accepted practice" to do this kind of thing in QT or is there some gotcha that I don't know of in the graphics view framework itself?
The Qt docs actually say quite a lot about thread safety. If the docs for QGraphicsScene don't say anything it's because they are not thread-safe, consistent with the behaviour you are seeing.
What you need to do is run your calculations in another thread and synchronise that thread with the main GUI thread as appropriate. A simple way to do this would be to set a flag in the main thread when the calculations are ready for display. That way you can call the appropriate QGraphicsScene methods in the main thread at the right time by simply checking the flag.
I am trying to develop am map application for scientific purposes at my university. Therefor I got access to a lot of tiles (256x256). I can access them and save them to an QImage in a seperate QThread. My Problem is, how can I actually manage to load the QImage into a texture within the seperate QThread (not the GUI main thread)? Or even better give me a Tipp how to approach this problem.
I though about multithreaded OpenGL but I also require OpenGL picking and I did not fall over anything usefull for that.#
Point me to any usefully example code if you feel like, I am thankfull for everything that compiles on Linux :)
Note1: I am using event based rendering, so only if the scene changes it gets redrawn.
Note2: OSG is NOT an option, it's far to heavy for that purpose, a leightweight approach is needed.
Note3: The Application is entirely written in C++
Thanks for any reply.
P.S. be patient, I am not that adavanced as this Topic may (or may not) suggest.
OpenGL is not thread-safe. You can only use one GL context in one thread at a time. Depending on OS you also have to explicitely give up on the context handle in one thread to use it in another.
You cannot speed up the texture loading by threading given that the bottleneck here is the bandwidth to the graphics card.
Let your delivery thread(s) that load the tiles fill up a ring buffer. The GL thread feeds from the ring buffer. With two mutexes it is easy to control the ring buffer to make this thread-safe operation.
That would be my suggestion.
Two tricks I use to speed things up:
pixel buffer objects: map GPU memory so the loading thread can write directly to gpu;
sync objects: with a sync object I know when the texture is really ready to be used (glTexImage2D with PBO is async so there is no guarantee the texture is ready to be binded, ie, when binding a texture, it blocks if DMA didn't finish updating texture data)