Qt Graphics and Performance – Whats Hot and whats Not

Posted by Gunnar Sletta on December 14, 2009 · 10 comments

On friday I added the following to the QPainter documentation:



    \section1 Performance

    QPainter is a rich framework that allows developers to do a great
    variety of graphical operations, such as gradients, composition
    modes and vector graphics. And QPainter can do this across a
    variety of different hardware and software stacks. Naturally the
    underlying combination of hardware and software has some
    implications for performance, and ensuring that every single
    operation is fast in combination with all the various combinations
    of composition modes, brushes, clipping, transformation, etc, is
    close to an impossible task because of the number of
    permutations. As a compromise we have selected a subset of the
    QPainter API and backends, where performance is guaranteed to be as
    good as we can sensibly get it for the given combination of
    hardware and software.

    The backends we focus on as high-performance engines are:

    \list

    \o Raster - This backend implements all rendering in pure software
    and is always used to render into QImages. For optimal performance
    only use the format types QImage::Format_ARGB32_Premultiplied,
    QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
    including QImage::Format_ARGB32, has significantly worse
    performance. This engine is also used by default on Windows and on
    QWS. It can be used as default graphics system on any
    OS/hardware/software combination by passing \c {-graphicssystem
    raster} on the command line

    \o OpenGL 2.0 (ES) - This backend is the primary backend for
    hardware accelerated graphics. It can be run on desktop machines
    and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
    specification. This includes most graphics chips produced in the
    last couple of years. The engine can be enabled by using QPainter
    onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
    command line when the underlying system supports it.

    \o OpenVG - This backend implements the Khronos standard for 2D
    and Vector Graphics. It is primarily for embedded devices with
    hardware support for OpenVG.  The engine can be enabled by
    passing \c {-graphicssystem openvg} on the command line when
    the underlying system supports it.

    \endlist

    These operations are:

    \list

    \o Simple transformations, meaning translation and scaling, plus
    0, 90, 180, 270 degree rotations.

    \o \c drawPixmap() in combination with simple transformations and
    opacity with non-smooth transformation mode
    (\c QPainter::SmoothPixmapTransform not enabled as a render hint).

    \o Text drawing with regular font sizes with simple
    transformations with solid colors using no or 8-bit antialiasing.

    \o Rectangle fills with solid color, two-color linear gradients
    and simple transforms.

    \o Rectangular clipping with simple transformations and intersect
    clip.

    \o Composition Modes \c QPainter::CompositionMode_Source and
    QPainter::CompositionMode_SourceOver

    \o Rounded rectangle filling using solid color and two-color
    linear gradients fills.

    \o 3x3 patched pixmaps, via qDrawBorderPixmap.

    \endlist

    This list gives an indication of which features to safely use in
    an application where performance is critical. For certain setups,
    other operations may be fast too, but before making extensive use
    of them, it is recommended to benchmark and verify them on the
    system where the software will run in the end. There are also
    cases where expensive operations are ok to use, for instance when
    the result is cached in a QPixmap.

I suspect it’s a piece of documentation many of you have been lacking for a while, and its something we should have put in a long time ago, but I can only say “sorry for not doing it sooner”. At least its getting done now. Note: Patch is not visible in public repository at the time of publishing. Should be there shortly

The urge to get these things into the docs have spun out from a number of dialogues I’ve had recently which all went pretty much like this:

  • TheOtherGirlOrGuy: My application is running slow… What do I do?
  • Me: What is it doing?
  • TheOtherGirlOrGuy: Well, its using QGraphicsView and QPainter and is doing this and that…
  • Me: That doesn’t sound too bad.
  • TheOtherGirlOrGuy: And then its really slow when doing this…
  • Me: Yeah… That doesn’t work very well. What you should be doing is this…
  • TheOtherGirlOrGuy:Is that written down someplace? How am I suppose to know that?
  • Me: Eh…

To remedy this, I’m going to put into action something I’ve had at the back of my head for a while now, a blog series on Qt Graphics and Performance. Along the way, I’ll also try to get parts of this into the documentation or into examples/demos as best practice use-cases.

I just have to point out, that this blog series is not a request for more features. It is about us sharing with you what we consider best practises and what our priorities are. Of course if you think our focus is way off, then let us know, but my primary intent with this blog series is to share some thoughts.

With the help of some of my co-workers, we plan to go through some Qt Graphics fundamentals, the “high-performance” engines, and usecases for graphicsview and widgets. If you have special usecases that you find interesting, then by all means let me know and maybe I can cover those too.

I need to add a small comment to the “drawText” case. It is currently not super optimal, because we have to do layout on the text for each time you call it. Because there is no “handle” in the function we don’t have the ability to cache the layout either. If we started caching based on a qHash of all the strings that were passed to drawText() then we end up caching a lot of single-shot text drawing… The option that we provide today to work around this is to use a QTextLayout with caching enabled, which is memory-wise quite hungry… I think in the range of 100-300 bytes pr character! So as an alternative, we are working on an API for static text which encapsulates the layout work with very little memory overhead. Its currently called QStaticText and we’re aiming for it to go into 4.7. Once it is in place, we’ll update the drawText comment in the performance documentation to be for these static texts…

As time permits we plan to push out blogs on the following topics:

  • An overview of the various components involved
  • The raster paint engine in detail
  • The OpenGL paint engine in detail
  • The OpenVG paint engine in detail
  • QGraphicsView optimization flags and cache modes
QShare(this)

No related posts.


10 comments

1 Editor dude December 14, 2009 at 3:01 pm
 

From the docs:

“…As a compromise we have selected a subset of the QPainter API and backends, were performance is…”

should be ‘…where performance is…’

2 Frederico Simas Duarte December 14, 2009 at 3:06 pm
 

Looking forward for this blog series.
Specially the OpenGL and QGraphicsView optimization parts.

3 gunnar December 14, 2009 at 3:33 pm
 

Editor dude: typos fixed, thanks!

4 cyril December 14, 2009 at 3:53 pm
 

This is really good news. I have been struggling with painter and paintdevices a lot and encountered catastrophic performance collapses too often, without having a clue what to do about it (especially on X11+Xrender). All hints you can give are highly appreciated! Please don’t forget to talk about reentrancy of the different paint engines.

5 Student December 14, 2009 at 5:34 pm
 

I’m planning on using QT to do traffic simulation (cars, streets, etc) in my master’s thesis, so I am keen on hearing any best practises connected with qt graphics :-)

6 Éverton Arruda December 14, 2009 at 6:02 pm
 

Looking forward for this blog series.
Specially the OpenGL and QGraphicsView optimization parts. [2]

7 Remi December 14, 2009 at 8:44 pm
 

A typical use case could be vector city maps (based on GIS data, with lots of overlapping polygons, paths, texts). QGraphicsScene optimization and good practices with ~500k items would surely be worth a blog entry too (but it’s probably off-topic this time as it’s not related to paint engines…)
Anyway, thank you for starting this new serie, I’m sure there will be a lot to learn form it!

8 scorp1us December 14, 2009 at 9:40 pm
 

I could really, really use those blog articles today!!! :-)

9 Kaitsu December 14, 2009 at 11:02 pm
 

Nicely delivered Gunnar!

It’s much better to get the facts from you Qt graphics guys who know the code instead of my “based on my testing, this seems fast/slow…”, especially as some corner-cases which used to be slow have now been improved.

So looking forward to this series, it’s surely time well spent from your side to improve not just the performance of Qt itself but also software using Qt!

10 SGD December 15, 2009 at 6:20 pm
 

I’d like to third the “Looking forward to OpenGL and QGraphicsView optimization” sentiment!

Comments on this entry are closed.

Previous post:

Next post: