Compressed Textures in Qt 5.11

As modern user interfaces become ever more graphics intensive, the demands on graphics memory to hold the textures increase. This is particularly relevant for embedded systems, where resources come at a higher premium, and can be a challenge for system performance. One of the key remedies for this is to reduce the memory requirements of the graphics assets.

OpenGL texture compression has the potential to give significant savings both in startup time and runtime performance:

  • Startup: no time required to uncompress the jpeg or png format
  • Startup: since the texture is much smaller, it requires significantly less time to upload it to GPU memory
  • Runtime: Significantly reduced strain on memory bandwidth
  • Decompression is very simple and happens in hardware, so does not pose significant drag down of performance

Compressed textures in Qt Quick 2

The Qt Quick 2 source code has for a long time included the textureprovider example. This showed how to expand Qt Quick with a custom image provider that could read simple ETC1-compressed textures from pkm format container files.

In Qt 5.10, that functionality was imported, somewhat silently, into Qt Quick itself. Hence, without further ado, one could now use a local pkm file or resource as the source of an Image element. In addition, support for ETC2 compression schemes was added.

Now in Qt 5.11, this functionality has been revamped and extended. Most importantly, support for ktx - the Khronos texture container file format - has been added. This format allows a much wider range of compression schemes, so Qt Quick is in practice only limited by what the target GPU and driver can handle.

screenshot

Using compressed texture files in a Qt Quick application requires nothing special. The key part of the qml code for the screenshot above is simply:

Grid {
columns: 2
Image { source: "slides.png" }
Image { source: "slides.ktx" }
...
}

As always, the memory savings comes at a cost. There is a trade-off between memory and visual quality. In the screenshot above, one can see how the bottom edges of the green area have become ragged compared to the original. The different texture compression schemes can provide different results, both in memory savings and image quality.

Transparency Trick

Special consideration must be taken for textures with transparency. For performance reasons, Qt Quick expects transparent textures to have the alpha channel pre-multiplied into the color channels. For normal images, Qt Quick takes care of this itself. But for compressed textures, it must necessarily be done before the image compression is performed. Some texture compression tools have built-in ability to do this. For those that do not, one can use other image manipulation tools to pre-process the source assets. For example, using ImageMagick, the following command line will create an image copy with pre-multiplied alpha:

convert mytexture.png \( +clone -alpha Extract \) -channel RGB
-compose Multiply -composite mytexture_pm.png

Note that the resulting mytexture_pm.png will not look right when viewed with a normal png viewer, since the png format itself does not handle pre-multiplied alpha. But after texture compression and loading into Qt Quick, it will be correct.

Fallback Fix

Now, what if one wants to run the application and the compressed texture files are not available, or not usable? Say, during development one may have only the original images available, or one may want to run on a target without OpenGL support. It is suboptimal to have a separate variant of the qml code for such cases. Naturally, there are many ways to solve this issue in Qt Quick. However, Qt 5.11 has added a little feature to the Image element that makes it particularly easy in many cases, namely automatic file extension detection. This means that if an Image element specifies a non-existing local file or resource name, Qt Quick will search for an image file with the same base name, by appending the known file extensions in turn. So, for example, if the code example above was changed to:

Image { source: "slides" }

Qt Quick will do the following:

  • First, if OpenGL is available, look for "slides.pkm" and "slides.ktx", and load the first file found, if any.
  • Then, if nothing loaded by step 1, look for "slides.jpg", "slides.png" etc., and load the first file found.

So, by just leaving out the file extension of the source file in the Qt Quick code, one has created a simple fallback mechanism.


Blog Topics:

Comments