You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I never get tired of having my own UI toolkit for PD. It allows for so many neat tweaks and adjustments that would otherwise be a nightmare (or straight-up impossible) to implement.
Case in point: this commit! One of the difficult things with a program like PD is that it needs to expose a *lot* of UI elements, especially on the main window. All the graphics required for the various toolboxes (especially if a complex tool like Advanced Text is active) add up quickly, and despite aggressive optimizations, GDI object count at a cold startup is still some ~250 objects, mostly DIB handles for each control's backbuffer.
Recent changes to improve UI responsiveness - like caching toolboxes after they've been used in a session - also cause GDI object count to climb during a session. Images with many layers, especially animated images, are also a challenge.
So in this commit, I've implemented a new strategy to help combat the potential for gradual resource climb.
First up, PD's central "pdDIB" object - the object that manages all arbitrary raster images - now provides a "Suspend" method. This function uses a compressor of your choosing (lz4 by default) to compress the current pixel buffer to an arbitrary memory stream, after which it will free all GDI objects associated with the image. The pixel data stays suspended until you attempt to access it (directly, or via an associated GDI handle, like a DC), at which point the class automatically recreates all necessary GDI objects and the original pixel buffer in the background. You never need to worry about calling "unsuspend" - it always happens automatically, as needed.
Alongside this new feature, I've started adding auto-suspend calls across a swath of UI code. When PD controls lose focus, they now suspend their backbuffer (since they're unlikely to render for awhile). Same for when they're hidden (a tricky one to implement, since Windows doesn't provide this notification automatically - fortunately, PD has a robust system in-place for inter-window communication).
Controls that maintain internal spritesheets, like toolbox buttons, will now also free their spritesheets after a successful render event.
This imposes no noticeable change to UI fluidity, but resource improvements are significant. On a cold start, PD has gone from ~250 GDI objects to just 148. Cold start memory usage is also down, and even if you open every toolbox in the program during a session, PD can now suspend all UI graphics for inactive toolboxes while still maintaining the windows themselves in the background, ready at a moment's notice. (GDI object requirements are down more than 70% in this scenario!)
I'll be adding more suspend triggers in the coming days, which should help to bring resource usage down even more. I love the idea of each new PD release being even *more* lightweight than the previous one - despite many new features - and this commit will help 9.0 reach that goal!
(This work was actually inspired by recent animation engine work, since animation frames pose a unique challenge for resource management. This new "suspend/resume" feature will be useful for further improving PD's resource management when working with animations, I think - I just need to do a lot of profiling first to ensure it doesn't affect animation timing accuracy.)
0 commit comments