Saturday, August 5, 2017

FMod - WPF investigations

Abiathar's graphics performance is bottlenecked by GDI+, which is apparently implemented entirely in software. Rerendering all planes every time the viewport moved is horribly slow, so since the beginning Abiathar has kept each plane's image cached. More recently, the rendering of tile planes was rewritten to use raw byte manipulation rather than GDI+. Unfortunately, Abiathar still isn't as fast as I would like - it shouldn't take a big machine to comfortably navigate some simple 2D graphics.

Windows Presentation Foundation graphics are hardware-accelerated, unlike Windows Forms. Rewriting Abiathar in WPF would be a huge task, and probably not worth it, but it's possible to embed WPF controls in WinForms. There are just a couple controls that are problematic - the level and tileset viewer panels - so replacing those should improve performance. There is rather a lot of infrastructure dedicated to rendering that is tied to the GDI+ way of doing things, so while the changes wouldn't be a complete rewrite, they wouldn't be trivial either.

So today I started a feasibility investigation to see how doable it would be to move to WPF for rendering. Starting small, I changed the selected tile images to be rendered with WPF. That involved creating a drawing context and converting the GDI+ bitmap to a WPF bitmap source On my first attempt, the selected tiles showed up, but were fuzzy due to the 2x scaling. After much Googling, I discovered I needed to set the bitmap scaling mode on the drawing context. Then I noticed that no key-down events were seen by the main form anymore. Apparently ElementHost doesn't respect KeyPreview, so one of the new controls was eating all the key events. With help from Stack Overflow, I switched to a custom control derived from ElementHost. (That code needed to be slightly adjusted to always pass the arrow key presses on.) And then I saw that the mouse clicks were not delivered to the selected tile images, even though I wired up event handlers on the host controls. Handling the event on the WPF control hosted inside worked, though.

So far, it seems doable to change the graphics over to WPF. I will continue this effort for now. If for some reason it doesn't help performance, I'll just roll back to before I started messing with it.

No comments:

Post a Comment