I have a graphics library for IoT devices here
GFX Forever: The Complete Guide to GFX for IoT[
^]
It is decoupled from its drivers, and you can write one any sort of display.
These displays usually only have one "mode" they can be in - at their native resolution and color depth.
However, some displays can present multiple "modes" of operation, wherein they utilize a different resolution or a different color depth or otherwise have other features (like partial updates on e-paper displays)
The trouble is a bit difficult to explain without some background, so let me start by saying a different color depth requires a different concrete type such that
bitmap<rgb_pixel<16>>
is a different type than
bitmap<rgb_pixel<24>>
or
bitmap<gsc_pixel<1>>
(last one is monochrome) - the example uses bitmaps for clarity but the same applies to screen modes as well.
That means I can't have one traditional
screen_mode()
function. It must be a template function that takes the screen mode as a template argument, like
screen_mode<0>()
because the type it returns will be different for each screen mode.
The other thing is, all of my draw surfaces, be they bitmaps or display drivers or screen modes (for drivers that expose more than one) are initialized on first use (but can be initialized earlier). They have to work that way.
With all of that in mind:
When I first draw to an uninitialized screen mode it will clear the display. it has to.
When I change screen modes I have to deinitialize the previous screen mode in the case that it holds a frame buffer in local RAM instead of on the display hardware (common for epaper and monochrome LCD)
This is before the new screen mode is initialized.
The screen will be blanked.
so if i go
auto mode0 = driver.template screen_mode<0>();
draw::filled_rectangle(mode0,
srect16(0,0,15,15).center((srect16)mode0.bounds()),
color<decltype(mode0)::pixel_type>::blue);
auto mode1 = driver.template screen_mode<1>();
draw::filled_rectangle(mode1,
srect16(0,0,15,15).center((srect16)mode1.bounds()),
color<decltype(mode1)::pixel_type>::purple);
draw::filled_rectangle(mode0,
srect16(0,0,15,15).center((srect16)mode0.bounds()),
color<decltype(mode0)::pixel_type>::red);
Note the comments. The first draw clears the screen due to initializing the driver (first use)
The second one clears the screen as the mode changes from 0 to 1
The third draw clears the screen as the mode changes from 1 to 0
My question to you is, how counterintuitive is this to you as a C++ developer, and can you think of a better way given the limitations I outlined?
What I have tried:
That kind of doesn't apply here, but I've tried exactly the code I presented, and it's currently the way I am doing things moving forward. I'm just not sure I like it.