Porting LVGL to classic Macintosh systems, all white display buffer


Hi there,

I’ve recently been exploring porting some modern GUI environments to classic 8MHz B&W Macintosh machines using the Retro68 toolchain (https://github.com/autc04/Retro68).

So far I’ve explored:

I’m interested in porting LVGL to these systems now as I think I can squeeze better performance out of it than nuklear or microui as I’ve been able to get ugui working relatively well by directly manipulating video memory, but ugui doesn’t have enough widgets to enable a lot of meaningful app development.

Anyways, I’ve started an LVGL-based Mac project at https://github.com/CamHenlin/LVGLQuickDraw using a similar memory manipulation strategy and am now at the point where I have it compiling, running, attempting to flush the display buffer, etc., but have been unable to get anything in LVGL’s display buffer.

How I got started on the LVGL project

I think it’s probably useful to chat about how I got the project started. I started by mashing up this tutorial around the linux framebuffer: https://blog.lvgl.io/2018-01-03/linux_fb and my previous ugui work at https://github.com/CamHenlin/UGUIQuickDraw. I also followed this forum post: Using LV_USE_THEME_MONO to set up my config file. I am using the exact lvgl and lv_driver versions from the linux_fb blog post and had to modify the libraries so upgrading is slightly non-trivial

Here you can see where I put the initialization code from the linux_fb blog post: https://github.com/CamHenlin/LVGLQuickDraw/blob/main/Sample.c#L99 and here you can see where I call the lv_task_handler which does result in a call through to the fbdev_flush function: https://github.com/CamHenlin/LVGLQuickDraw/blob/main/Sample.c#L159, but when flushing, no pixels appear to have any color but white

What did I do to the LVGL codebases?

As you might note in https://github.com/CamHenlin/LVGLQuickDraw if you look around, I had to modify LVGL a bit to get it running on the Mac. Firstly, I had to rip out #include <stdbool.h> references and replace them with #include <MacTypes.h>, and replace every bool reference with Boolean which should behave the same as the previous bool types (and is something MacTypes implements). I’m not sure that I can use stdbool on the Mac system at all (because it causes conflicts with MacTypes) and have had luck following this strategy on other projects

Next, you’re probably saying to yourself “this is setup to use the linux_fb, of course that’s not going to work!!!” and you’d be right, except I also modified the fbdev.c driver heavily: https://github.com/CamHenlin/LVGLQuickDraw/blob/main/lv_drivers/display/fbdev.c. Of note here, everything linux-related has been ripped out, and fbdev_flush is modified to use another function putpixel to modify the Mac’s video memory directly. This is where I am seeing problems but I’m not entirely sure this is where my problem lies.

As you can see here: https://github.com/CamHenlin/LVGLQuickDraw/blob/main/lv_drivers/display/fbdev.c#L138, I’m attempting to log out every non-white pixel. The trouble is, this never logs anything at all. I would expect this to produce logging on the pixels making up “Hello world!”. I am confident putpixel works because it is used in the aforementioned ugui project and because if I manually set the final parameter (where color_p->full is being used) to 1, I will successfully black out the screen.

My question

If I’m not seeing anything but white pixels, when I am expecting to be seeing at least a few black pixels making up “Hello world!”… Where should I be looking? I have good logging capabilities via serial port output (as you probably noticed with the writeSerialPort function calls), but I don’t have any type of debugging capabilities.

What MCU/Processor/Board and compiler are you using?

Motorola 68000@8MHz, 4MB memory, running GCC and the Retro68 toolchain (https://github.com/autc04/Retro68)

Thank you for reading!

Also, I sincerely apologize for needing to do GITHUB_URL, LVGL_BLOG_URL, and LVGL_FORUM_URL in my post. Unfortunately the forum software would not allow me to post links

First of all, interesting project!

Can you try enabling LVGL logging and see if there are any errors?

(I’ve edited your post to fix the links and also increased your trust level so the forum software doesn’t block you from linking again.)

Thanks for the edit! :slight_smile:

I’ll get logging setup today, I’ll have to modify the logging code to dump the log messages over the serial port so it will take a slight amount of effort. I’ll post back with the results!

You can configure a custom logging function.

Alright, that was pretty easy to get logging going - I love how thoughtful LVGL is with this kind of stuff!

Here is what my log output looks like with LV_LOG_LEVEL_TRACE set

call fbdev_init
call lv_disp_buf_init
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 222, fn_name: lv_obj_create, dsc: Screen create started
INFO: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 409, fn_name: lv_obj_create, dsc: Object create ready
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 222, fn_name: lv_obj_create, dsc: Screen create started
INFO: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 409, fn_name: lv_obj_create, dsc: Object create ready
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 222, fn_name: lv_obj_create, dsc: Screen create started
INFO: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 409, fn_name: lv_obj_create, dsc: Object create ready
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_widgets/lv_label.c, line: 80, fn_name: lv_label_create, dsc: label create started
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 254, fn_name: lv_obj_create, dsc: Object create started
INFO: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_obj.c, line: 409, fn_name: lv_obj_create, dsc: Object create ready
INFO: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_widgets/lv_label.c, line: 168, fn_name: lv_label_create, dsc: label created
call into event loop
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_misc/lv_task.c, line: 74, fn_name: lv_task_handler, dsc: lv_task_handler started
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_refr.c, line: 176, fn_name: _lv_disp_refr_task, dsc: lv_refr_task: started
in fbdev flush
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_refr.c, line: 285, fn_name: _lv_disp_refr_task, dsc: lv_refr_task: ready
TRACE: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_misc/lv_task.c, line: 192, fn_name: lv_task_handler, dsc: lv_task_handler ready

I haven’t started digging in on this much this morning but will be tinkering around some more today

Making a bit of progress here, between adding in LVGL logging and enabling LV_USE_DEBUG in the conf file, I’ve now got the following to investigate:

WARNING: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_misc/lv_mem.c, line: 209, fn_name: lv_mem_alloc, dsc: Couldn't allocate memory
WARNING: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_misc/lv_mem.c, line: 319, fn_name: lv_mem_realloc, dsc: Couldn't allocate memory
ERROR: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_style.c, line: 484, fn_name: _lv_style_set_opa, dsc: _lv_style_set_opa
ERROR: : file: /home/camh/Documents/Retro68kApps/LVGLQuickDraw/lvgl/src/lv_core/lv_debug.c, line: 188, fn_name: lv_debug_log_error, dsc: Out of memory (0x00000000)

I think this should be fixable since I have 4MB of memory to work with, doing some further investigation into what’s happening

edit: I switched out LV_MEM_CUSTOM in the conf to 1, which gives me stdlib’s malloc and free - this resolves the error but I’m still dealing with the same result of all white pixels. Will continue investigation

Progress! I’ve done a few things so far:

  • Upgraded to latest vanilla LVGL 7.11 release (no more using MacTypes instead of stdbool)
  • Modified MacTypes and a few other Mac headers to no longer make use of MacTypes’s Boolean, allowing me to prevent the collision with stdbool and use LVGL unmodified

Now, I’m not getting any errors, the “Hello world!” text is still not displaying… but! I added LV_USE_PERF_MONITOR to my config, and now I am getting the FPS properly displaying at the bottom of my window. This was not happening prior to swapping out to vanilla LVGL 7.11

So, getting closer!


The performance counter should be displayed in the exact bottom right of the window. In your picture it seems to be off so I think your display driver may have an issue.

More progress!

I think I’m having some issues with the mono theme which was causing my text to not display. I can’t get the mono theme to display anything but the FPS counter, which I agree looks off by a bit - will be trying to address that later this evening.

Now using the material theme, with LV_COLOR_DEPTH set to 1, I’m able to run the lv_demo_widgets() function, and everything displays! I think it would look better on the mono theme, but progress is progress!


Okay, I was able to fix the offset issues pretty easily. That turned out to just be a mismatch between the LVGL resolution configuration and the size of my window, so everything is peachy there.

Now however I am getting myself pretty convinced that the mono theme is broken or that I am failing to understand something about it.

If I use the material theme in 1 color mode, I’m able to get this:

These are the settings I’m using to achieve that:


#define LV_THEME_DEFAULT_INCLUDE            <stdint.h> 
#define LV_THEME_DEFAULT_INIT               lv_theme_material_init
#define LV_THEME_DEFAULT_FONT_SMALL         &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_NORMAL        &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_SUBTITLE      &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_TITLE         &lv_font_montserrat_12

But if I use the mono theme, I can only get this out - with everything else across my entire codebase the same:

and these are the settings that I’m trying:

#define LV_USE_THEME_MONO        1

#define LV_THEME_DEFAULT_INCLUDE            <stdint.h> 
#define LV_THEME_DEFAULT_INIT               lv_theme_mono_init
#define LV_THEME_DEFAULT_FLAG               0
#define LV_THEME_DEFAULT_FONT_SMALL         &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_NORMAL        &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_SUBTITLE      &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_TITLE         &lv_font_montserrat_12

Does anyone have any ideas of what I’m doing wrong here?

For now I am going to roll with using the material theme and focus on getting input working, but I’d still like to understand what’s going on with the mono theme, or what I’m doing incorrectly with it.

I think something might still be up with your driver - notice how the 0 is cut off in 100% CPU.

Hmm, maybe you’re on to something there. Can you recommend any tests I could run to prove that? Of note, when I watch the UI draw in initially, I see the 0, fully, then it’s drawn over a split second later. I’m not sure what would be causing my driver to do that because my driver is pretty dead simple and just modifying individual video memory bits while having no trouble drawing the rest of the UI.

I can’t think of any specific tests, besides manually calling the flush function with random areas and colors, and confirming that the results match what you expect.

It’s possible that this is triggered by the downlevelling from color to monochrome, but in that case I would expect this to happen consistently with both zeros, and in your case it only happens to the left one and the U in CPU.

This suggests that the driver may be handling partial refreshes incorrectly, though I would expect you to see other, more severe symptoms if that were the case.

I started working on getting inputs going today and made good progress. I have the mouse working, keyboard inputs going, but things aren’t quite usable yet. As suspected, I definitely having some kind of video driver issue that I need to figure out. It looks to me like updates are coming in somewhere to the left of where they need to be whereas the initial full screen draw looks good.


Here’s a screenshot after clicking the “cancel” button on the modal in the middle of the demo for example.