GraphicsView: Merging of update regions and optimization implications
I spent some time optimizing my painting code for a pretty old-fashioned embedded device, and came across an interesting fact that could have implications even on faster systems:
When I update several rectangles on a single GraphicsItem, they are automatically merged into a single larger rectangle.
“So what?” you might say. Well, it has some performance implications, which I’ll cover a bit later. I certainly did not find this behavior documented, not within the QGraphicsItem’s update method or anywhere else I looked.
Plus, I am using the flag “MinimalViewportUpdate”, which promises:
“QGraphicsView will determine the minimal viewport region that requires a redraw, minimizing the time spent drawing by avoiding a redraw of areas that have not changed.”
I was perplexed, until I stepped through Qt’s source code, and found that the single update rectangles of a single GraphicsItem are merged into one rectangle.
What are the implications?
One of the architectural decisions when designing a GraphicsView-based painting system is: Inheritance or Composition?
Inheritance (in this context) means that I create custom graphical items by inheriting from QGraphicsItem, and doing the painting myself. Those items can be quite complex and very task-specific.
Using composition, I create the scene by composing it from existing GraphicsItem classes (QGraphicsPixmapItem, QGraphicsLineItem,…).
Usually, both approaches are combined when creating complex scenes. And this leads to an optimization limitation due to the (implicitly) merged update areas:
Assume you have a custom graphics item covering a large area, and lots of small items on top of it.
The large custom item combined relatively static data (e.g. a background pixmap), and some dynamic data (e.g. a few labels that can change on occasion).
If a single label changes, all I need to redraw is the label’s area. However, if two labels change, at worst on opposite corners of the item, a large portion of the item has to be redrawn, thereby also redrawing many of the small items on top – unnecessarily.
Unrealistic? It strongly reminds me of the example shown in the
labs blog [labs.qt.nokia.com] some time ago
I wouldn’t say it’s a regular case, but certainly a realistic one.
Fortunately, there’s a solution: Split the custom graphics item into items that display static data, and items that display changing data. Then, the update regions can be kept separate.