Hello, I’m considering updating an old application from GTK 2 to GTK 4. I don’t plan to make significant changes to how it works, but will have to update how it displays some shapes on screen.
The application visualizes a basic building plan/blueprint with some dynamic (moving, changing) polygonal shapes (maybe they can be called sprites? Not sure) drawn on top. It currently does this by drawing the building plan and other background shapes into a “background” GdkPixmap(using gdk_draw_polygon() etc.) This is initially copied into a “foreground” GdkPixmap with gdk_draw_pixmap(), and that foreground pixmap is drawn in the window. Then every frame (approx. 10 fps) it determines what regions have changed (because the foreground shape/sprite changed or moved) and need to be redrawn: that region is copied from the background pixmap into the foreground pixmap (on top of the changed region), then each dynamic shape that changed is re-drawn in the foreground pixmap. Finally the foreground pixmap is redrawn on the window (GtkWindow, again using gdk_draw_pixmap()). The user can pan and zoom the view which the application also implements itself by just redrawing everything with different transformation applied to everything. (not using any GTK widget to implement scrolling or zooming.)
I’m wondering if simply replicating this process with Cairo and GdkPixbufis a good choice, or if there is a system in Cairo, Gdk, Gsk, etc that essentially implements a similar process, and maybe does it more efficiently (perhaps with less copying of pixels)? Any suggestions on how to find this out, where to look in examples or documentation?
Hello, in GTK4 a possible way to handle this would be to create a GskCairoNode for each shape that you want to draw with cairo. You can store them in the widget like you would a pixmap and then render them as necessary in the snapshot function if you are writing a custom widget. There you can transform them or move them around using the other GSK APIs too.
GdkPixbuf is a class for loading images, so likely you want to avoid it unless you are loading some images you know it supports. In that case you would use the constructors in GdkTexture and then create some GskTextureNodes to draw the images.
If you are layering multiple textures together like that then you generally cannot avoid copying the pixels a lot, but GSK nodes will be cached as GPU textures for fast redrawing.
Sounds interesting, thanks. Is there any introductory/tutorial documentation for GSK? I only see the API reference at docs.gtk.org.
Is there any direct equivalent to GdkPixmap now? An object that is focused on storing and accessing a bitmap raster image – a pixel buffer or pixel image which can be used as the target of Cairo drawing operations? Is it GdkTexture?
GdkPixmap was a thin wrapper around X11 server side pixel buffers; there’s nothing in GTK4 that covers that, considering that X11 is legacy, at this point.
GdkTexture is an immutable buffer that is used to upload data to the GPU.
If you want to render something with Cairo and keep it around, use a Cairo image surface; you can then take the contents of the surface and upload them to a GdkTexture; or you can use the image surface as the source when drawing on a GskCairoNode.
Practically speaking, though, if you have an area of your application that is going to be drawn using Cairo, you can use GtkDrawingArea; it will deal with taking the contents of a Cairo context and put them into the GTK rendering pipeline.