Skip to content

Display and UI

Prefer the Host-provided LVGL table for ordinary UI. Write directly to the framebuffer only when you need per-pixel control.

Drawing text and controls#

  1. Include gm_plugin_lvgl_api.h and obtain the API table from host->graphics.lvgl.
  2. Check the table version, struct_size, and the functions you use.
  3. Call root_get() in on_start and create controls such as label and obj under the returned root.
  4. Update the UI with Host functions such as label_set_text, obj_set_pos and obj_set_size.
  5. Drive interaction with on_event and on_loop. On stop, release the objects you created without deleting the Host root.

Direct framebuffer drawing#

display_get_info reports the actual geometry. lock(y, &surface) returns the Host tile containing that row. Follow the returned y, height, stride, and pixel format, then unlock after drawing. GRAY_4 uses 4 bits per pixel, with two pixels in each byte.

  • Drawing the full frame may require iterating over multiple tiles. Do not assume a fixed half-screen tile size.
  • Submit intermediate tiles with present=false and only the last tile with present=true.
  • Do not call LVGL while holding the framebuffer lock. Later LVGL refreshes may overwrite overlapping regions.
  • Start by reusing the drawing flow in GlassSDK/examples/framebuffer, then change its content.

Images and animation#

Images and frame animation require LVGL API 1.1. First check GM_PLUGIN_VERSION_COMPATIBLE(ui->api_version, GM_PLUGIN_VERSION(1U, 1U)), ui->struct_size >= GM_PLUGIN_LVGL_API_1_1_SIZE, and the function pointers you use. Passing only the LVGL 1.0 minimum table-size check is insufficient for these new members.

ContentsLayout and processing
Image formatGM_PLUGIN_LVGL_IMAGE_INDEXED_4BIT: a 64-byte palette (16 BGRA8888 entries) followed by row-by-row 4-bit pixel indices. Do not pass PNG/JPEG file bytes directly.
Pixel PositionEach row uses ceil(width / 2) bytes, without extra row padding. Even x uses the high 4 bits; odd x uses the low 4 bits. Palette alpha participates in compositing, but the final display remains GRAY_4.
Resource life cycleThe Host copies descriptors and animation frame lists but borrows pixel data. Keep that data valid and unchanged until you replace the source or delete the object.
Start Animationanim_image_create does not start playback. Configure the frames and timing, then call anim_image_start. A repeat count of 0 plays once; use GM_PLUGIN_LVGL_ANIM_REPEAT_INFINITE to loop.

Calculate memory use before increasing image size#

Each frame's pixel resource uses 64 + ceil(width / 2) × height bytes; multiply by the number of frames. One 75 × 65 frame uses 2534 bytes, and 4 frames use 10136 bytes. Application state, stack, messages, and temporary working memory require additional space.

  • Reducing dimensions and frame count reduces resident memory. Increasing frame duration only lowers the update rate; it does not reduce stored frame data.
  • Compressed ZIP size does not represent GMP runtime memory use. Add assets gradually and check outputs and physical-device behavior after each build.

Reference files in the toolkit#

  • GlassSDK/include/gm_plugin_lvgl_api.h
  • GlassSDK/docs/GRAPHICS.md
  • GlassSDK/examples/image_animation