I was finally able to reproduce an interesting/annoying issue today, and it turned out that I remembered my intent to blog about it from last time. Here’s the result.
Some windows would fail to render until they either resized or changed their visuals (damages).
It was difficult to pin down exactly what triggered this issue since I had only heard of it from others without actually experiencing the issue first hand. In general, rendering issues are impossible for me to fix unless I can get them under a gdb scope, so I wasn’t spending too much time trying to figure it out; in most cases, these types of issues are the ones that I fall face first into at some point. As expected, that point was today while working on yet another Yakuake-related issue (fuck you, shaped windows, even though it was unrelated to shapes).
When I did discover a way to reproduce this, I was a bit confused since it only happened in this one particular case (Yakuake menus in Xephyr after restarting E, and only after the menu had already been shown once). Something like a sacrifice to the rendering daemons to get the app to break, I guess? Anyway, I buckled in for a long debugging session which ended up not being very long at all.
Here’s a shot of my workspace upon encountering the problem:
Immediately after examining my rendering debug output, I spotted the problem, which I’ve cut out into a smaller image:
The compositor was rejecting the render updates! I added this functionality during the rewrite to avoid rendering before objects got sized initially, so it was obvious to me what was occurring in the pipeline at this point:
- Client appears
- Client resizes
- Client runs its render update
- Client attempts to trigger rendering on itself
- Client fails to trigger rendering on itself
- Client shows
No further render updates were pending, so the rendering never occurred even though all the information for the render was available. As proof, here’s what would happen when I moved the cursor over the area occupied by the non-rendered window:
Tada, the menu appears because it received damages and triggered more render updates:
Lots of render updates, in fact; there may be some overdraw here which can be eliminated at some point.
The STUNNING Conclusion:
After checking on a few things internally, I confirmed that events were occurring as I previously hypothesized, which meant that I just had to add in a flag to track when a client was ready for rendering and then add a render update when that client was shown if the flag was set. The entire commit was ~10 lines of changed code, and now things render as expected.
This ended up being a relatively easy “hard” bug since render debugging is very informative, but it may give some insight as to how the process works.