Skip to content

Friday, 8 November 2024

Let’s go for my web review for the week 2024-45.


Voted in America? This Site Doxed You

Tags: tech, democracy

I didn’t know the voting rolls were public record in the US… this is a really bad idea.

https://www.404media.co/voted-in-america-this-site-doxed-you/


One weird trick to get the whole planet to send abuse complaints to your best friend(s)

Tags: tech, networking, security, protocols

Looks like there are people out there to get Tor relays down… and they found a smart networking trick I’d expect to not work anymore.

https://delroth.net/posts/spoofed-mass-scan-abuse/


XMPP: the forgotten gem of Instant Messaging

Tags: tech, xmpp, ux

Could XMPP make a come back if the user experience was better?

https://adele.pages.casa/md/blog/xmpp-the-forgotten-gem-of-instant-messaging.md


A conceptual model of ATProto and ActivityPub

Tags: tech, protocols, fediverse, governance, decentralized

Interesting explanation of the different visions and governance behind ActivityPub and ATProto.

https://fediversereport.com/a-conceptual-model-of-atproto-and-activitypub/


A Map of Sync

Tags: tech, syncing, data

Interesting dimensions to use when classifying syncing solutions and to see which ones will meet your constraints.

https://stack.convex.dev/a-map-of-sync


DuckDB over Pandas/Polars

Tags: tech, databases, data-science

A good reminder that I should probably evaluate DuckDB for some of my tooling.

https://pgrs.net/2024/11/01/duckdb-over-pandas-polars/


Why systemd is a problem for embedded Linux

Tags: tech, systemd, embedded

This is a good point. systemd is kind of turning into a monoculture, but what are we loosing? Indeed, right now things could be better on deeply embedded systems (I insist on the “deep embedded” here which is often more limited in resources). Unlike the author I think they could be improved and they don’t quite apply to a good chunk of recent embedded platforms though.

https://kevinboone.me/systemd_embedded.html


How the New sqlite3_rsync Utility Works

Tags: tech, databases, sqlite, tools, syncing

If you wonder how the protocol is designed and how the actual implementation works, this is a nice introduction. Clearly it’s helped by the size of that program which is fairly small.

https://nochlin.com/blog/how-the-new-sqlite3_rsync-utility-works


C++, Complexity, and Compiler Bugs

Tags: tech, c++, complexity

Good illustration of how the C++ language complexity is out of hands.

https://azeemba.com/posts/cpp-complexity-compiler-bugs.html


Having fun with modern C++ – Daniel Lemire’s blog

Tags: tech, c++

Still, C++ improved in recent years. The problem is that we tend to stick too much to the old constructs we already know and that things keep piling up but nothing is removed.

https://lemire.me/blog/2024/11/02/having-fun-with-modern-c/


smolweb HTML specification

Tags: tech, html, accessibility, low-tech, complexity

A nice subset of HTML to ensure better accessibility and reduced complexity.

https://smolweb.org/specs/index.html


Tags: tech, web, frontend, html

Each has a use, they shouldn’t be conflated. It makes for poor user experience and accessibility otherwise.

https://marijkeluttekes.dev/blog/articles/2024/11/04/html-link-or-button-that-is-the-question/


Long Distance Relationships

Tags: tech, remote-working, management, product-management

A bit biased toward stable product teams only. Still, there are good tips which are more widely applicable here. This gives a good idea of the management of a distributed team of remote workers.

https://matt.blwt.io/post/long-distance-relationships/



Bye for now!

I spent past three weeks working on refactoring and fixing legacy code (the oldest of which was from 2013) that handled positioning Plasma desktop icons, and how this data was saved and loaded.

Here's the merge request if you're curious: plasma-desktop: Refactor icon positioner saving and loading

The existing code worked sometimes, but there were some oddities like race conditions (icon positioning happens in weird order) and backend code mixed in with frontend code.

Now I am not blaming anyone for this. Code has tendency to get a bit weird, especially over long periods of time, and especially in open source projects where anyone can tinker with it.

You know how wired earbuds always, always get tangled when you place them in a drawer or your pocket or something for few seconds? Codebases do the exact same thing, when there are multiple people writing on things, fixing each others' bugs. Everyone has a different way of thinking, so it's only natural that things over time get a bit tangled up.

So sometimes you need someone to look at the tangled codebase and try to clear it up a bit.

Reading code is the hardest part

When going through old code, especially some that has barely any comments, it can take a very long time to understand what is actually going on. I honestly spent most of my time trying to understand how the thing even works, what is called when, where the icons positions are updated, and so on.

When I finally had some understanding of what was happening, I could start cleaning things up. I renamed a lot of the old methods to be hopefully more descriptive, and moved backend code — like saving icon positions — from the frontend back to backend.

Screens and icons

Every screen (PC monitor, TV…) tends to have it's own quirks. Some, when connected with display-port adapter, tell your PC it's disconnected if your PC goes to screen saving mode. Some stay connected, but show a blank screen.

One big issue with the icon positions was that when screen got turned off, it thought there was no screen anymore and started removing items from the desktop.

That's fair. Why show desktop icons on a screen that is non-existent? But when you have a monitor that tells your PC, "Okay I'm disconnecting now!" when the PC says it's time to sleep, wrong things would happen.

This condition is now handled by having a check that if the screen is in use or not. Now when screen is not in use, we just do nothing with the icons. No need to touch them at all.

Stripes and screen resolution

Our icon positioning algorithm uses something called "stripes."

Every resolution has it's amount of stripes. Stripes contain an array of icons, or blank spots.

So if your screen resolution is, let's say, 1920x1080, we calculate how many stripes and how many items per stripe will fit on that screen.

Stripe1: 1 2 3 4 5 6 7
Stripe2: 1 2 3 4 5 6 7
Stripe3: 1 2 3 4 5 6 7

And so on..

But when you change your screen resolution or scale factor, how many icon stripes you have and how many icons fit on each stripe will change.

So if you have one of those screens that looks to the system like it's been unplugged when it goes into sleep mode, previously the stripe amount would change to 1 row, 1 column. And the icon positioner would panics and shove all icons in that 1,1 slot.

Then when you'd turn the screen back on, the icon positioner would wonder what just happened and restore the proper stripe number and size. But by that point it would have lost all our positioning coordinate data during the shoving of icons in that one miniscule place, so instead it would reset the icon positions… and this leaves users wondering why their desktop icon arrangement is now gone.

Here we have to also check for the screen being in use or not. But there were other problems.

Saving icon positions

The prior code saved the icon positions every time the positions changed. Makes sense.

But it didn't account for the screen being off… so the icon positions would get saved while the desktop was in a faulty state. This also causes frustration because someone arranges the icons how they wish, but then screen does something weird and they're now saved in wrong places again.

Our icon positions were updated after almost every draw call, if the positions changed. So this would mean the saving would happen rather often and no matter what moved them.

We had to separate the user action from computer action. If computer moves the icons, we ideally do not save their positions, unless something drastic has happened like resolution change.

The icon positions are saved per resolution, so if you move icons around while they're displayed on a 3440x1440 screen and then change the resolution to 1920x1080, both will have their own arrangements. This part of the codebase did not previously work, and it would always override the old configuration, which caused headache.

So now we only save icon positions when:

  • The user adds or removes a desktop icon
  • The user moves a desktop icon
  • The user changes the desktop resolution

This makes the icon position saving much less random, since it's done only after explicit user actions.

Margin errors

The last thing that caused headaches with the icon positioning was that the area available on the desktop for icons was determined before panels were loaded. When the panels loaded, they would reduce the amount of space for desktop icons, and that area would constantly resize until everything is ready.

In previous code, this would cause icons to move, which updates positions, which then saves their positions.

So let's say you arrange your icons nicely, but the next time you boot into plasma, your panels start shoving the poor icon area around and the icons have to move out of the way… and now they're all in the wrong places.

This was already partially fixed by not saving when the computer moves the icons around: we just load the icon positions when the screen is in use and we are done with listing the icons on the desktop. Part of the margin changes happen when screen is off.

We still need to fix the loading part; ideally we load the icon area last, so that it gets the margins it expects and doesn't shuffle around while panels are still appearing. But it was out of scope for this merge request.

Conclusions

It may not sound like much, but this was a lot of work. I spent days just thinking about this problem, trying to understand what is happening now and how to improve it.

Luckily with a lot of help from reviewers and testers I got things to work much better than it used to. I am quite "all-over-the-place" when I solve problems so I appreciate the patience they had with me and my questions. :D

What I mostly wished for when working on this were more inline code comments. You don't need to comment the obvious things, but everything else could use something. It's hard to gauge what is obvious and what is not, but that kind of answers the question: If you don't know if it's obvious or not, it's likely not, so add some comment about it.

I do hope that the desktop icons act more reliably after all these changes. If you spot bugs, do report them at https://bugs.kde.org.

Thanks for reading! :)

PS. The funniest thing to me about all of this is that I do not like having any icons on my desktop. :'D

Thursday, 7 November 2024

The last maintenance release of the 24.08 series is out. We fixed some issues, so project opening should be working again.

Wednesday, 6 November 2024

While I do have a Qt git build on my machine that I use for development, I usually only test individual applications and functionality but hardly ever run my full Plasma session on it. This means that for day-to-day use I typically only get to enjoy new Qt features once they have actually been released.

Message Box “Close Document: The document has been modified. Do you want to save your changes or discard them?” ontop of a KWrite editor window that is darkened because the prompt is modal
Proper modal dialogs under Wayland (note the darkened editor window) thanks to XDG Dialog and the new Qt 6.8

One feature I talked about in the very last issue of “On the road to Plasma 6” is a nice API for XDG Foreign. To recap: it’s a Wayland protocol that lets an application export a window to another one so it can can attach a window to it. For example, the XDG Desktop Portal wants to attach the “Open File” dialog as if it were coming from the application that requested it.

Of course we don’t want to write low-level Wayland code and instead have an easy to use API for it. The KWindowSystem::setMainWindow function does just that: hand in a window and the token you received from the other application (created through KWaylandExtras::exportWindow) and it takes care of everything else. Presumably, you want to set the parent window before showing your dialog to make absolutely sure it’s set up properly.

However, Qt did not have an API to tell us when the underlying XDG Toplevel (think: a regular desktop-y window with a title bar and what not) had been created. We were only told when the basic wl_surface was created, which was too early, or the window was exposed/shown, at which point it was already flashing up in the user’s task bar. Hence, I added a new QWaylandWindow::surfaceRoleCreated (and corresponding surfaceRoleDestroyed) signal. Utilizing that, the aforementioned KWindowSystem API now works perfectly.

Another major addition to Qt Wayland that I have been looking forward to very much is support for the XDG Dialog protocol. While a window could have always had a parent (e.g. a popup menu or settings dialog parented to the application’s main window), there was no concept of a “modal” dialog. Therefore, we did not support the “dim parent” effect under Wayland that darkens a window to indicate it cannot be interacted with. More importantly, KWin couldn’t take it into account for its focus handling either. It happily let you focus a blocked window but the application would then just ignore your input.

Thumbnail of two confirmation boxes “This window contains multiple tabs. Are you sure you want to close the window?“ side by side, “Confirmation” window title overlaid ontop of the thumbnail.
There’s only one Dolphin running here!

This was most noticeable for me when Alt+Tab’ing back and forth, for example using the “Open File” dialog in one application and then trying to switch to the other to verify where the file was actually located. Instead of cycling between the file dialog and the other application, it would alternate between the file dialog and the blocked main window.

Sadly, even when I upgraded to Qt 6.8 the situation didn’t improve. I noticed that Alt+Tab actually showed the dialog twice. This looked like a bug and sure enough comparing it to the Plasma 5.27 LTS session on my other computer proved that it used to work at some point. At first I didn’t spot anything obvious until I noticed a small typo that must have slipped in during some major refactoring. Instead of not including the main window when it had a modal child, it included the modal child once again! Sure enough, adding an exclamation mark (the logical NOT operator in C++) did the trick.

If you want to support more good people such as myself, consider donating to the KDE End of Year Fundraiser!

Tuesday, 5 November 2024

This one required a few other features to be implemented first, so let’s jump right in.

Matching reference luminances

A big part of what a desktop compositor needs to get right with HDR content is to show SDR and HDR content properly side by side. KWin 6.0 added an SDR brightness slider for that purpose, but that’s only half the equation - what about the brightness of HDR content?

When we say “HDR”, usually that refers to a colorspace with the rec.2020 primaries and the perceptual quantizer (PQ) transfer function. A transfer function describes how to calculate a real brightness value from the “electrical” signal encoded in the content - PQ specifically has encoded values from 0 to 1 and brightness values from 0 to 10000 nits. For reference, your typical office monitor does around 300 or 400 nits at maximum brightness setting, and many newer phones can go a bit above 1000 nits.

Now if we want to show HDR content on an HDR screen, the most straight forward thing to do would be to just calculate the brightness values, write them to the screen and be done with it, right? That’s what KWin did up to Plasma 6.1, but it’s far from ideal. Even if your display can show the full range of requested brightness values, you might want to adjust the brightness to match your environment - be it brighter or darker than the room the content was optimized for - and when there’s SDR things in HDR content, like subtitles in a video, that should ideally match other SDR content on the screen as well.

Luckily, there is a preexisting relationship between HDR and SDR that we can use: The reference luminance. It defines how bright SDR white is - which is why another name for it is simply “SDR white”.

As we want to keep the brightness slider working, we won’t map SDR content to the reference luminance of any HDR transfer function though, but instead we map both SDR and HDR content to the SDR brightness setting. If we have an HDR video that uses the PQ transfer function, that reference luminance is 203 nits. If your SDR brightness setting is at 406 nits, KWin will just multiply the brightness of the HDR video with a factor of 2.

This doesn’t only mean that we can make SDR and HDR content fit together nicely on HDR screens, but it also means we now know what to do when we have HDR content on an SDR screen: We map the reference luminance from the video to SDR white on the screen. That’s of course not enough to make it look nice though…

Tone mapping

Especially with HDR presented on an SDR screen, but also on many HDR screens, it will happen that the content brightness exceeds the display capabilities. To handle this, starting with Plasma 6.2, whenever the HDR metadata of the content says it’s brighter than the display can go, KWin will apply tone mapping.

Doing this tone mapping in RGB can result in changing the content quite badly though. Let’s take a look by using the most simple “tone mapping” function there is, clipping. It just limits the red, green and blue values separately to the brightness that the screen can show.

If we have a pixel with the value [2.0, 0.0, 2.0] and a maximum brightness of 1.0, that gets mapped to [1.0, 0.0, 1.0] - which is the same purple, just in darker. But if the pixel has the values [2.0, 0.0, 1.0], then that gets mapped to [1.0, 0.0, 1.0], even though the source color was significantly more red!

To fix that, KWin’s tone mapping uses ICtCp. This is a color space developed by Dolby, in which the perceived brightness (aka Intensity) is separated from the chroma components (Ct = blue-yellow, Cp = red-green), which is perfect for tone mapping. KWin’s shaders thus transform the RGB content to ICtCp, apply a brightness mapping function to only the intensity component, and then convert back to RGB.

The result of that algorithm looks like this:

RGB clippingKWin 6.2’s tone mappingMPV’s tone mapping
HDR image with clippingHDR image with KWin's tonemappingHDR image with MPV's tone mapping

As you can see, there’s still some color changes going on in comparison to MPV’s algorithm; this is partially because the tone mapping curve still needs some more adjustments, and partially because we also still need to do similar mapping for colors that the screen can’t actually show. It’s already a large improvement though, and does better than the built-in tone mapping functionality in many HDR screens.

When tone mapping HDR content on SDR screens, we always end up reducing the brightness of the overall image, so that we have some brightness values to map the really bright highlights in the video to - otherwise everything just slightly over the reference luminance would look like an overexposed blob of color, as you can see in the “RGB clipping” image. There are ways around that though…

HDR on SDR laptop displays

To explain the reasoning behind this, it helps to first have a look at what even makes a display “HDR”. In many cases it’s just marketing nonsense, a label that’s put on displays to make them seem more fancy and desirable, but in others there’s an actual tangible benefit to it.

Let’s take OLED displays as an example, as it’s considered one of the display technologies where HDR really shines. When you drive an OLED at high brightness levels, it becomes quite inefficient, it draws a lot of power and generates a lot of heat. Both of these things can only be dealt with to a limited degree, so OLED displays can generally only be used with relatively low average brightness levels. They can go a lot brighter than the average in a small part of the screen though, and that’s why they benefit so much from HDR - you can show a scene that’s on average only 200 nits bright, with the sky in the image going up to 300 nits, the sun going up to 1000 nits and the ground only doing 150 nits.

Now let’s compare that to SDR laptop displays. In the case of most LCDs, you have a single backlight LED for the whole screen, and when you move the brightness slider, the power the backlight is driven at is changed. So there’s no way to make parts of the screen brighter than the rest on a hardware level… but that doesn’t mean there isn’t a way to do it in software!

When we want to show HDR content and the brightness slider is below 100%, KWin increases the backlight level to get a peak brightness that matches the relative peak brightness of that content (as far as that’s possible). At the same time it changes the colorspace description on the output to match that change: While the reference luminance stays the same, the maximum luminance of the transfer function gets increased in proportion to the increase in backlight brightness.

The results is that SDR white gets mapped to a reduced RGB value, which is at least supposed to exactly counteract the increase of brightness that we’re applying with the backlight, while HDR content that goes beyond the reference luminance gets to use the full brightness range.

Increasing the backlight power of course doesn’t come without downsides; black levels and power usage both get increased, so this is only ever active if there’s HDR content on the screen with valid HDR metadata that signals brightness levels going beyond the reference luminance.

As always, capturing HDR content with a phone camera is quite difficult, but I think you can at least sort of see the effect:

without backlight adjustmentwith backlight adjustment
without backlight adjustmentwith backlight adjustment

This feature has been merged into KWin’s git master branch and will be available on all laptop displays starting with Plasma 6.3. I really recommend trying it for yourself once it reaches your distribution!

KDAB Training Day - May 8th, 2025

Early-Bird tickets are on sale for the KDAB Training Day 2025 until 2025-03-31 23:59

training-day-long-banner.png

The KDAB Training Day 2025 will take place in Munich on May 8th, right after the Qt World Summit on May 6th-7th. Choose to buy a combo ticket here (for access to QtWS and Training Day) or here (for access to Training Day only).

Seats are limited, so don't wait too long if you want to participate in a specific course. Tickets include access to the selected training course, training material, lunch buffet, beverages, and coffee breaks. Note: The Training Day is held at Hotel NH Collection München Bavaria, located at the Munich Central Station (not the same location as Qt World Summit).

Get your ticket

Why should you attend the KDAB Training Day?

With over 20 years of experience and a rich store of well-structured, constantly updated training material, KDAB offers hands-on, practical programming training in Qt/QMLModern C++3D/OpenGLDebugging & Profiling, and lately Rust - both for beginners as well as experienced developers.

All courses provided at the Training Day include central parts of the regular 3- to 4-day courses available as scheduled or customized on-site training. Choosing a compact, learning-rich one-day course, lets you experience the quality and effectiveness of KDAB’s usual training offerings.

Courses available at the KDAB Training Day 2025

  • QML Application Architecture
  • QML/C++ integration
  • Modern C++ Paradigms
  • Integrating Rust into Qt applications
  • Effective Modern QML
  • Integrating Custom 3D Renderers with Qt Applications

QML Application Architecture

In this training, we do a step-by-step walkthrough of how to build a QML-based embedded application from the ground up and discuss some challenges that are typically met along the way.

An important part of that journey is an investigation of where to put the boundaries between what you do in C++ and what you do in QML. We also look at some of the tools and building blocks we have available in QML that can help us achieve well-performing, well-structured, and well-maintainable applications.

This course is for

(Qt) developers looking to improve their understanding of how to construct maintainable and efficient larger-scale QML applications.

Prerequisite

Some real-world experience working on QML applications as well as a basic understanding of Qt and C++.

Get your ticket

QML/C++ Integration

In this training, we start with a recap of fundamentals:

  • How do we expose C++ API to QML?
  • How do we make data available to QML?

Afterward, we explore several more advanced techniques, often widely deployed within Qt's QML modules, such as Qt Quick.

This will answer questions such as:

  • How would I do a Loader like component?
  • How would I do a Layout like component?

This course is for

Qt/QML developers who are familiar with the QML APIs of QtQuick and related modules and who have wondered how these are implemented and want to use similar techniques in their project-specific APIs.

Prerequisite

Some real-world experience working on QML applications as well as a basic understanding of Qt and C++.

Get your ticket

Modern C++ Paradigms

Modern C++ emphasizes safer, more efficient, and maintainable code through higher-level abstractions that reduce error-prone manual work.

This training will explore key paradigms shaping recent C++ evolution, starting with value semantics in class design, which enhances code safety, local reasoning, and thread safety. We will examine modern C++ tools for creating value-oriented types, including move semantics, smart pointers, and other library enablers.

Next, we will look at expressive, type and value-based error handling.

Finally, we'll cover range-based programming, which enables clean, declarative code and unlocks new patterns through lazy, composable transformations.

This course is for

C++ developers who wish to improve the quality of their code, in particular those who wish to write future-proof APIs.

Prerequisites

Prior professional experience in C++. Experience with the latest C++ standards (C++20/23/26) is a plus. We will use several examples inspired by Qt APIs, so Qt knowledge is also a plus (but this is not going to be a Qt training).

Get your ticket

Integrating Rust into Qt Applications

In this step-by-step course, we start with a Qt/C++ application and add Rust code to it piece by piece. To achieve this, we will cover:

  • Use of Cargo (Rusts build system) with CMake
  • Accessing Rust code from C++ with CXX (and vice-versa)
  • Defining your own QObject types in Rust with CXX-Qt

We discuss when to use Rust compared to C++ to make the best of both languages and how to use them together effectively to make Qt applications safer and easier to maintain.

This course is for

Qt/C++ Developers with an interest in Rust who want to learn how to use Rust in their existing applications.

Prerequisites

Basic Qt/C++ knowledge, as well as basic Rust knowledge, is required. A working Qt installation with CMake and a working Rust installation is needed. We will provide material before the training day that participants should use to check their setup before the training.

Get your ticket

Effective Modern QML

In this training, we look into all the new developments in QML over the last few years and how they lead to more expressive, performant, and maintainable code.

This includes:
- The qt_add_qml_module CMake API
- Declarative type registration
- The different QML compilers
- New language and library features
- New developments in Qt Quick Controls
- Usage of tools like qmllint, QML Language Server, and qmlformat

The focus will be on gradually modernizing existing codebases with new tools and practices.

This course is for

Developers who learned QML back in the days of Qt 5 and want to catch up with recent developments in QML and modernize their knowledge as well as codebases.

Prerequities

Some real-world experience with QML and a desire to learn about modern best practices.

Get your ticket

Integrating Custom 3D Renderers with Qt Applications

Qt has long offered ways of using low-level 3d libraries such as OpenGL to do custom rendering. Whether at the Window, the Widget, or Quick Item level, the underlying rendering system can be accessed in ways that make it safe to integrate such 3rd party renderers. This remains true in the Qt 6 timeline, although the underlying rendering system has changed and OpenGL has been replaced by RHI.

In this course, we look at how the graphic stack is structured in Qt 6 and how third-party renderers can be integrated on the various platforms supported by Qt.

We then focus on the specific case of integrating Vulkan-based renderers. Vulkan is the successor to OpenGL; it's much more powerful but harder to learn. To facilitate the initial use of Vulkan, we introduce KDGpu, a library that encapsulates Vulkan while preserving the underlying concepts of pipeline objects, buffer handling, synchronization, etc.

This course is for

This course targets developers wanting to understand the recent state of the graphics stack in Qt, discover the fundamental principles of modern graphics API, and integrate their custom renderers in their applications.

Prerequisite

Prior knowledge of Qt will be required. A basic understanding of 3d graphics would be beneficial.

Get your ticket

Video from KDAB Training Day 2023 held in Berlin

The post KDAB Training Day - May 8th, 2025 appeared first on KDAB.

In many cases, importing data into LabPlot for further analysis and visualization is the first step in the application:

LabPlot supports many different formats (CSV, Origin, SAS, Stata, SPSS, MATLAB, SQL, JSON, binary, OpenDocument Spreadsheets (ods), Excel (xlsx), HDF5, MQTT, Binary Logging Format (BLF), FITS, NetCDF, ROOT (CERN), LTspice, Ngspice) and we plan to add support for even more formats in the future. All of these formats have their reasons for existence as well as advantages and disadvantages. However, the performance of reading the data varies greatly between the different formats and also between the different CPU generations. In this post, we’ll show how long it takes to import a given amount of data in four different formats – ASCII/CSV, Binary, HDF5, and netCDF.

This post is not about promoting any of the formats, nor is it about doing very sophisticated measurements with different amounts and types of data and extensive CPU benchmarking. Rather, it’s about what you can (roughly) expect in terms of performance on the new and not so new hardware with the current implementation in LabPlot.

For this exercise, we import the data set with 1 integer column and 5 columns of float values (Brownian motion for 5 “particles”, one integer column for the index) with 50 Millions of rows which results into 300 Millions of numerical values:

We take 6 measurements for each format, ignore the first measurement, which is almost always an outlier due to the disk cache in the kernel and results in faster file reads on subsequent accesses, and calculate the averages:

As expected, the file formats that deal with binary representation internally (Binary, HDF5, NetCDF) provide significantly better performance compared to ASCII, and this difference becomes larger the slower the CPU is. The performance of HDF5 and NetCDF is almost the same because the newer version of NetCDF is based on HDF5.

The implementation in the data import code is straightforward. Ignoring for a moment the complexity with the different options affecting the behavior of the parser, different data types and other subleties, once everything is set up it’s just a matter of iterating over the data, parsing it and converting it into the internal structures. The logic inside the loop is fixed, and a linear behavior with respect to the total number of values to read is expected. This expectation is confirmed using the same CPU (we took the fastest CPU from the table above) and varying the total number of rows with the fixed number of columns:

The performance of the import is even more critical when dealing with external data that is frequently modified. In order to provide a smooth visualization in LabPlot for such “live data”, it’s important to optimize all steps involved here, like the import of the new data itself, as well as the recalculation in the algorithms (smoothing, etc.) and in the visualization part. For the next release(s), we’re now working to further optimize the implementation to handle more performance-critical scenarios in the near future. The results of these activities, funded by the NLnet grant, will be the subject of a dedicated post soon.

Update: we have fixed the issue and the update is rolling out in the beta channel. The production channel still uses 5.2.3, but that will be updated later.

On releasing the latest version of Krita in our Android/ChromeOS beta program, we discovered, too, late that there was a problem that could prevent Krita from starting.

Since the Google Play Store Console does not allow revering a release to an earlier version, we are now urgently working on a fix which we will release as soon as possible.

Our apologies for the inconvience.

The currentl nightly builds for Android work again, with some limitations:

  • take care removing the store version of Krita does not remove the application data: your artwork could be lost.
  • in the Nightly builds you need to install any brush presets separately

You can get the night builds here: Krita Next Nightly Builds. You will need to select the package that is right for the architecture of your device.

Installing the nightly builds requires enabling developer mode on your device and needs considerable technical insight.

If you do not feel comfortable with this, please wait until the new official release lands in the play store in a about two days.

Saturday, 2 November 2024

Surprise! This blog post series has now been moved to blogs.kde.org so it’s now open for others to participate and contribute! This week’s post can be found at https://blogs.kde.org/2024/11/02/this-week-in-plasma-spoooooky-ooooooooom-notifications

That’s probably where it should have been all along, as this work is much bigger than me. I’ll remain the editor-in-chief for now, but do welcome contributions to help lighten the load. 🙂

Unfortunately, due to GDPR restrictions, I’m unable to migrate existing email subscribers to the new email digest over there. So if you’d like to re-subscribe to “This week in Plasma.” head to https://newsletter.kde.org/subscription/form and re-subscribe.

I’ll still be blogging here about KDE topics of interest to me and hopefully you as well, just not the weekly Plasma news. So I do hope you’ll stick around. 🙂

Friday, 1 November 2024

In Plasma 6.2, KWin switched from doing linear blending with HDR to blending in a gamma 2.2 space. Let’s take a look at what that means, and why it was done.

What is blending?

When KWin composites, it paints window by window, going by the order of how the windows are stacked - the bottom-most window first, the topmost window last. When a window is opaque, you just overwrite the pixels in the framebuffer with the ones from the window. When a window is semi-transparent though, we need to additionally do blending.

To do blending, the GPU calculates the value that the framebuffer should have with some equation that gets the pixel from the window and the existing value in the framebuffer, and outputs some appropriate value. Usually that equation is1

framebuffer = framebuffer.rgb * (1 - window.alpha) + window.rgb * window.alpha

where window.alpha is a per-pixel value that describes how opaque the pixel is.

Blending with color management

In Plasma 5, compositing happened in the display color space. As displays could be assumed to be roughly the same, with brightness levels encoded in sRGB, that resulted in blending looking very similar everywhere.

With HDR in Plasma 6 however, that assumption was no longer true, so we had to do something else. As it was considered the most “correct” thing and allows us to ensure the exact same blending result even with displays that have wildly different colorspaces, linear blending was chosen for Plasma 6.0. The result of linear blending would look different from sRGB, but it would at least be consistent everywhere.

With linear blending, instead of just taking the rgb values as is, you first convert them into light-linear values, for example with sRGB you’d just do

rgb_linear = pow(rgb_sRGB, 2.2)

then apply the blending equation, and at the end convert it back to whatever encoding the screen needs.

Because of limitations in KWin’s renderer and the ancient OpenGL versions KWin supports, the only way to do this was to render first into a so-called shadow buffer2 with linear values, and after compositing a second shader pass would run, taking that shadow buffer as the input and outputting a buffer with non-linear values that’s suitable for sending to the screen.

The caveats of linear blending

It’ll be pretty obvious to most that doing a fullscreen copy each frame is not ideal for performance or battery life, but there was even a second problem: If you use only 8 or 10 bits per color (bpc) to store linear brightness values, you get visible banding in the dark areas of the image, as human vision is very non-linear. So on top of doing fullscreen copies, KWin also had to use a floating point buffer with 16 bpc, which uses twice the memory bandwidth vs. 8 bpc and makes performance and power usage even worse.

With that performance hit, we couldn’t enable this on all hardware, but had to restrict linear blending to those displays where HDR or an ICC profile is enabled. This threw the whole consistency benefit out of the window, because now a semi-transparent surface would look a lot more transparent just because you enabled HDR… causing the very problem we wanted to avoid!

SDRHDR
gamma 2.2 blendinglinear blending

We had to do something when blending in HDR though, so a different approach had to be taken.

Custom transfer functions

When storing colors in buffers, usually we use non-linear encodings with transfer functions like sRGB or PQ. All the transfer functions have some sort of luminance levels attached to them, for example an sRGB value of 1.0 is defined to result in a luminance of 80 nits in its reference viewing environment3.

There’s no reason to be restricted to those definitions though - we can make transfer functions that mean whatever we want or need. In KWin’s case, we switched the shadow buffer from using a linear encoding to a gamma 2.2 encoding, in which 1.0 means the maximum luminance of your monitor. This means we do blending in a very similar way as on SDR screens4, and translucent surfaces on the screen look pretty much the same again, no matter what display settings you have.

As the gamma 2.2 encoding allocates more numbers to darker parts of the image, we can also avoid banding with fewer bits per color. Whenever HDR is enabled and the driver supports buffers with 10 bpc, KWin now prefers to use that instead of 16 bpc, alleviating some of the performance issues. There was still more that could be done though…

KMS offloading

On most graphics cards, the scanout hardware that takes care of sending the image to the display has some fixed function blocks to change the colors in various ways - the most common being a simple look up table (LUT) per color channel.

Through the DRM/KMS API, the compositor can set this LUT, so we can use it to change the encoding from whatever we did blending in to the one the display needs. With HDR screens, this means we

  • convert from our shadow buffer encoding with gamma 2.2 and the maximum luminance of the screen to linear
  • possibly apply rgb factors for night light
  • convert from linear to the PQ encoding the screen needs

With that LUT in place, we don’t have to run a shader pass to convert from the shadow buffer encoding to the screen anymore, so the whole fullscreen copy falls away.

Except for a few additional instructions in the shaders used for compositing, enabling HDR in Plasma 6.2 thus has no performance impact anymore on the vast majority of hardware!





  1. in practice, window.rgb is already “pre-multiplied” with window.alpha, but that doesn’t really matter here 

  2. it’s called that because it’s never actually shown on the screen 

  3. the viewing environment basically defines a standardized room, in which the content can be viewed as intended without doing any brightness adjustments 

  4. it’s not exactly the same though. If you need some exactly specific blending behavior in your application, it’s best if you do it yourself