gunnar
Uncategorized
Qt
KDE
Graphics View
Painting
Graphics Dojo
Posted by gunnar
 in Uncategorized, Qt, KDE, Graphics View, Painting, Graphics Dojo
 on Wednesday, October 22, 2008 @ 08:24

There have been a number of requests to be able to replace the rendering engine used for widgets and pixmaps to be either OpenGL or the Raster backends as these have much better support for more advanced graphics features, such as gradients, blending and transformations compared to, specially, the X11 painting backend.

There existed some previous tricks to swap these things around. For instance, it was common to do “setViewport(new QGLWidget())” on a graphicsview it if ran slow. Similarly, one could create a QImage the size of the widget and do paintEvent into the QImage and just copy the data at the end using QPainter::drawImage().

Now we provide you with the real option. Starting Qt 4.5 you can choose the graphics system to use. It is ready available in the Technology Preview and in the snapshots. The way to pick backend is currently to specify a command line argument: “-graphicssystem raster” for the software engine or “-graphicssystem opengl” for OpenGL. The OpenGL graphicssystem is considered experimental for 4.5, while the raster backlend is considered fully supported on all platforms.

“But hey, this means we have tons of XPutImage calls as part of the repainting, doesn’t it?” you are probably thinking. Luckily not… The raster graphics system is using the X Shared Memory extension to allocate the bits shared with an XPixmap so the end of a paint is a mere XCopyArea, which happens in-place on the X server, so it is quite cheap. Needless to say this is a solution that works best on local displays, but that does cover most of the Linux desktops out there, so it should be a gain in general.

Using this also means that QPixmaps reside in system memory and QImage < -> QPixmap conversions are cheap, making things like smoothScaled significantly faster. Another nice side effect is 100% feature compliance as the raster backend is the reference implementation of QPainter. In general you should expect speedups in anything related to svg’s, pixmap transformations and gradients when switching to the raster system.

Just to give you an idea, below you see results of running the svgviewer with the bubbles.svg file on the various systems

Windows (Intel Core 2 Quad 2.6 GHz, 4 GB Ram, NVidia GeForce 8500 GT)

  • Native: 60 Fps
  • Raster: 60 Fps
  • OpenGL: 245 Fps

Naturally, Native and Raster run at the same speed on windows because native is the raster backend.

X11 (Intel Pentium 4, 3 GHz, 1 Gb Ram, Nvidia GeForce 6600)

  • Native: 20 Fps
  • Raster: 36 Fps
  • OpenGL: 92 Fps

This machine is running a slightly older graphics card than the other two machines, but its still a significant boost compared to native and raster when running with OpenGL.

Mac OS X (PowerBook, Intel Core 2 Duo, 2.4 GHz, 4 GB Ram, NVidia GeForce 8600 GM)

  • Native: 9 Fps
  • Raster: 30 Fps
  • OpenGL: 215 Fps

So, to sum up, any Qt application can now be run with the command line option

> app -graphicssystem raster

or

> app -graphicssystem opengl

and it will use a different rendering backend. So to underlying graphics libraries we say:
“So long and thanks for the Blit!”

23 Responses to “So Long and Thanks for the Blit!”

» Posted by Lubos Lunak
 on Wednesday, October 22, 2008 @ 11:43

Just curious, did you really mean to say shared pixmaps? The ones that e.g. http://www.nvnews.net/vbulletin/showthread.php?t=118088 refers to as

Option “AllowSHMPixmaps” “0″
This option prevents applications from allocating Shared Memory pixmaps. While such pixmaps generally yield better performance using non-accelerated operations, they can’t be permanently stored in video memory by the NVIDIA X driver. As this causes the NVIDIA X driver to be unable to optimally accelerate rendering operations involving such pixmaps, it is highly recommended that you set this option to 0 for best performance.
Please note: EXA drivers generally disable Shared Memory pixmaps, as well.
” ?
Unless you in fact meant shared images, you may possibly have a little problem there.

» Posted by Frédéric COIFFIER
 on Wednesday, October 22, 2008 @ 11:52

About remote connections with X11, I use the NX (http://www.nomachine.com/) improved protocol. I found Qt4 really slower than Qt3 through NX/FreeNX (In fact, at office, we use a big Linux server with KDE 3.5 and remote clients with NXclient and after some tests, KDE 4 seemed unusable).

I’ve just made some test on Qt4.5 with different -graphicssystem and the ‘browser’ demo and it seems that, strangely, opengl graphicssystem provides the best performance through the NX protocol. It’s just a feeling as I don’t know how to quickly measure that.

» Posted by sroedal
 on Wednesday, October 22, 2008 @ 11:59

Lubos: the raster graphicssystem doesn’t use any accelerated rendering, everything is done in software. Remarkably, this is usually faster than using XRender when it comes to pixmap transforms and gradients for example. The final offscreen image is then blitted to the X window using an X pixmap, and this is where the Shared Memory extension combined with XCopyArea comes into play. At least in our measurements this has been faster than using XPutImage to blit the image to the X window.

» Posted by Lubos Lunak
 on Wednesday, October 22, 2008 @ 12:28

sroedal: Uhm, no, read again. The point is the Shared Memory extension (the shared pixmap part of it, that is), according to that, won’t come into play, since eventually it will be disabled pretty much everywhere. Just get nvidia-177.80 driver, set the option and watch what happens next (I don’t feel like trying for real, but I can guess). XRender sucks, but it’ll be probably still faster than this.

» Reply from gunnar
 on Wednesday, October 22, 2008 @ 12:35
gunnar

Lubos: The X11 paint engine currently falls back to software rendering for advanced features like gradients, pixmap transformations, etc. We have tried to use XRender for these features to have the stuff done on the X server but the best results we’ve seen are that XRender is half the speed of doing it in software and doing an XPutImage afterwards. Hence… This provides you the option of doing all the rendering in software on the client side, and not doing all the XPutImage per drawing operation, but rather by doing one Blit at the end. If shared memory is available we use that, if not, then its not that big a deal. The benchmarks above run at 2Fps lower when Shared Memory Extension is disabled, which is still tons better than what we would have gotten from using XRender.

» Posted by andyed
 on Wednesday, October 22, 2008 @ 13:25

Mac OS X (PowerBook, Intel Core 2 Duo, 2.4 GHz, 4 GB Ram, NVidia GeForce 8600 GM)

Native: 9 Fps
Raster: 30 Fps
OpenGL: 215 Fps

Raster faster than Native on Mac OS X is this correct?

» Posted by reed
 on Wednesday, October 22, 2008 @ 13:46

Is there a way to set the graphicsssytem other than a command line option? A function the app can call? Or a registry or config file entry?

» Reply from gunnar
 on Wednesday, October 22, 2008 @ 13:49
gunnar

andyed: This is correct. Our software backend for QPainter is faster than our CoreGraphics backend for most things. The CoreGraphics engine is faster than the raster engine when drawing large areas, because these operation are H/W accellerated by CoreGraphics, but in general our software engine beats native rendering on Mac OS X.

There is one architectural clash that causes some performance problems on the CoreGraphics backend, and that is state handling. CoreGraphics uses the PDF / PostScript model where you can only intersect a new clip with current clip and only multiply a new transformation with the existing one. Neither of the two states can be reset, only saved / restored. QPainter allows setting these states (and you can argue if this is wise or not, but it feels practical and its the way QPainter works so we don’t want to change it) regardless of what they previously was which means we need to do some nasty save/restore-stack handling on the CoreGraphics side, which is not fortunate performance wise…

Then there is the problem that CoreGraphics has a fixed overhead on all drawing operations. The fastest I’ve gotten is some 100.000 plain rectangles pr second (small ones, 4×4, 8×8, etc), while our software engine can do 10x that and style code and general widget code contains a lot of these small primitives, so the cost accumulates.

The benchmark does only repaints one widget, while an application is typically contains multiple widgets and the repaint / flush-to-screen logic is not optimal for Mac OS X at the moment, so an app like Designer won’t run any faster with -graphicssystem raster. We hope to be able to spend more time on those things in the coming months to iron out these things and make it really shine.

» Reply from gunnar
 on Wednesday, October 22, 2008 @ 13:50
gunnar

reed: not currently, but we intend to add such methods. We’re thinking of configure flag, config file, function call in addition to the command line parameter.

» Posted by manyoso
 on Wednesday, October 22, 2008 @ 14:33

Gunnar, this is great news! I am very happy with this development. Also, I agree with reed on the need for a programmatic way of setting the graphics subsystem on a particular widget or a particular app. I wonder, is it even possible to set the graphics subsystem of a particular widget while the rest of the widgets in the application use a different graphics subsystem? I doubt it, but would be very cool if we could do this in the future.

» Reply from gunnar
 on Wednesday, October 22, 2008 @ 14:43
gunnar

manyoso: There won’t be a way to change the backend for a single widget. The reason for this is that the widget is not responsible for its own drawing. The backingstore, which is one per toplevel widget, is the one that provides the paint engine using by QPainter in the paintEvent() so if there were to be an option to change graphicssystem for individual parts of an application it would have to be for the toplevel only. The embedded version of Qt already has the option of switching graphicssystems per toplevel, so we have been discussing moving this into Qt, but nothing is decided here

» Posted by koder
 on Wednesday, October 22, 2008 @ 15:14

Can we expect new themes based on a OpenGL pain engine to follow. It would be really cool to get really nice 3D beveling and lighting effects on ordinary widgets. Granted we can now do this with pixmaps, but pixmaps but pixmaps don’t optimize very well across different displays, and SVG is probable to slow.

» Posted by David Johnson
 on Wednesday, October 22, 2008 @ 16:44

The raster backend sounds exciting, but I’m not sure about OpenGL. The quality of rendering from driver to driver can vary tremendously. At least this is what I’ve seen using OpenGL for Graphics View. I think it’s because so many drivers are optimized for hi-fps games and not desktop display. For some clients it will be great but you can’t rely on it for all of them.

» Posted by Dennis
 on Wednesday, October 22, 2008 @ 16:55

Maybe you should look how you use XRender and why this causes software fallbacks at the xserver. The usage of A1 pixmaps is a good example here. Most cards can’t accelerate them (or with special shader workarounds), EXA for example even disables them for accelerations completely.

Another tip is to not use XShmPixmaps as they won’t be supported in most configurations in the future. XShm(Put|Get)Image will still work.

» Posted by Benjamin Poiesz
 on Wednesday, October 22, 2008 @ 21:39

Hi Gunnar! This is pretty awesome, but I had one question about a possible good side effect of using the OpenGL engine. Do you support placing a QWidget with a transparent background over an QGLWidget, like for example…A QLabel over a QGLWidget? If so…AWESOME!

» Reply from gunnar
 on Thursday, October 23, 2008 @ 06:39
gunnar

koder: There aren’t any plans for 3D based styles, but who knows what the open source community will think of :)

David: The quality of rendering is the reason why we call the GL engine experimental for now. It is tricky to get pixel perfection using GL, but there are ways to get pixels into the right places. The high quality anti-aliasing is one example, but of course, its current implementation is not really that much faster than the raster engine. We won’t say that GL is a viable option until we see that its good enough.

Dennis: The shared pixmaps are used if available, if not we do a XPutImage, so its a benefit if its there, still works if its not there. What we observe currently is that our software engine is faster than what we do with XRender. As for the future, I certainly hope we get our open gl engine to a state where it can kick the software engines butt and use GL all over, hence the lack of shared memory pixmaps etc won’t be an issue. We’ll be faced with a completely new set of things to overcome, but that’s software for you :)

Benjamin: You can do this already if you embed a QWidget in a QGraphicsView where the viewport is a GL Widget. You would do your paintGL() code as part of the scenes drawBackground() and let the widgets reside as parts of the scene. You won’t be able to simply overlay a QWidget on a QGWidget I’m afraid, as the widgets live in the backingstore (a pbuffer or fbo) and the QGLWidget is an isolated context that lies on top of the backingstore. It needs to be that way because we don’t necessarily want to interfere with the GL state / config of the QGLWidget.

» Posted by damien m
 on Thursday, October 23, 2008 @ 12:41

great, could you give a sample code ?

» Posted by Benjamin Poiesz
 on Thursday, October 23, 2008 @ 15:41

Hi Gunnar. Thanks for the reply, but I have tried the QGraphicsView trick in the past, but found the performance overhead of doing so to be too high. I am animating multiple widgets atop a QGLWidget that is refreshing at 30FPS, and just putting the QGraphicsView on drastically lowers the framerate. My current solution using fully custom QWidgets rendering in a QGLWidget, so I’ll keep doing that. Would have been nice to use the bulit-in Qt widgets… Thanks though.

» Posted by sroedal
 on Friday, October 24, 2008 @ 07:53

damien: If you refer to the QGraphicsView technique with a QGLWidget viewport and embedded widgets on top, see http://labs.trolltech.com/blogs/2008/06/27/accelerate-your-widgets-with-opengl/

Benjamin: There shouldn’t be any significant performance loss from using QGraphicsView. The svgviewer example, which was used as the benchmark above has been modified to use QGraphicsView in 4.5, achieves very high framerates when using OpenGL (this goes both for using a QGLWidget viewport and using the new OpenGL graphics system). There are choices that might affect your rendering performance though like whether to use the QGraphicsItem cache modes or not. Also, in Qt 4.5 a lot of optimizations have gone into QGraphicsView too, so feel free to give it another try if you want.

» Posted by Robert Knight
 on Friday, October 24, 2008 @ 18:28

Ouch! -graphicssystem opengl kills my system (Ubuntu Intrepid, Intel graphics) with some interesting psychedelic flashing. Might be worth a warning in the release notes. Great to see work on this though.

» Posted by hjpriester
 on Monday, October 27, 2008 @ 10:34

I tried this option with the a snapshot I compiled last week. (17-10). on Linux.
Our appplication a simple 2D vector editor does not performance good.

- no commandline option: after zooming in 2 times application becomes very slow….. (compaired with QT 4.3.5)

-graphicssystem raster: text is missing, zooming is faster and after zooming in 3 times appear

-graphicssystem opengl: also very slow when zooming in, rubberbanding is slow, scrolling etc.
( might be caused by the OpenGL support on my system)

So my first impression is not very positive hope it will improve……

» Posted by steven
 on Tuesday, October 28, 2008 @ 08:38

Hi Sroedal,

This is very interesting. Here I have a question about embedding widgets into QGLWidget through QGraphicsView. We want to use VirtualGL (http://www.virtualgl.org/) to have remote OpenGL rendering (through virtualGL a faked GLXContext is created locally). I’m want to know for the cache mode, is the widget rendered into a pixmap at first and then loaded into texture? I’m afraid that it will be very slow to render into pixmap at server and then read back to texture at client side? Could the widget directly being rendered into texture (frame buffer object)? Can you please explain me a little when the widget is being rendered into QGLWidget, what functions will be called related to X server side? Thanks!

Regards,
-Steven

» Posted by Adam Higerd
 on Wednesday, October 29, 2008 @ 17:46

It’s nice to see that you edited the Mac stats into the article, but when you did so it appears a spambot hijacked… something or another… and the whole thing is now a link to Cialis spam.



© 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
All other trademarks are property of their respective owners.