diff --git a/components/micropython/usermodule/mp_sys_display.c b/components/micropython/usermodule/mp_sys_display.c
index 6f425743283fc8feb5609e7d476dd97a207c48b6..e06da6daa8ffc488f26909901c2899da85040926 100644
--- a/components/micropython/usermodule/mp_sys_display.c
+++ b/components/micropython/usermodule/mp_sys_display.c
@@ -105,6 +105,17 @@ STATIC mp_obj_t mp_update(mp_obj_t ctx_in) {
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_update_obj, mp_update);
 
+STATIC mp_obj_t mp_drop(mp_obj_t ctx_in) {
+    mp_ctx_obj_t *self = MP_OBJ_TO_PTR(ctx_in);
+    if (self->base.type != &mp_ctx_type) {
+        mp_raise_ValueError("not a ctx");
+        return mp_const_none;
+    }
+    st3m_gfx_drop_frame(self->ctx);
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_drop_obj, mp_drop);
+
 STATIC mp_obj_t mp_pipe_full(void) {
     if (st3m_gfx_pipe_full()) {
         return mp_const_true;
@@ -133,6 +144,7 @@ STATIC const mp_rom_map_elem_t mp_module_sys_display_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_pipe_available), MP_ROM_PTR(&mp_pipe_available_obj) },
     { MP_ROM_QSTR(MP_QSTR_pipe_flush), MP_ROM_PTR(&mp_pipe_flush_obj) },
     { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mp_update_obj) },
+    { MP_ROM_QSTR(MP_QSTR_drop), MP_ROM_PTR(&mp_drop_obj) },
     { MP_ROM_QSTR(MP_QSTR_fb), MP_ROM_PTR(&mp_fb_obj) },
     { MP_ROM_QSTR(MP_QSTR_ctx), MP_ROM_PTR(&mp_ctx_obj) },
     { MP_ROM_QSTR(MP_QSTR_fps), MP_ROM_PTR(&mp_fps_obj) },
diff --git a/components/st3m/st3m_gfx.c b/components/st3m/st3m_gfx.c
index 16f49f3348c8f5bd92cc3856cb4d648147dd81c7..eca44fe50ba8a7d100c6026e5e223df82223396d 100644
--- a/components/st3m/st3m_gfx.c
+++ b/components/st3m/st3m_gfx.c
@@ -1026,21 +1026,33 @@ static void st3m_gfx_pipe_put(void) {
 }
 
 static Ctx *st3m_gfx_ctx_int(st3m_gfx_mode mode);
-void st3m_gfx_end_frame(Ctx *ctx) {
+
+static int end_frame(Ctx *ctx) {
     ctx_restore(ctx);
 #if CONFIG_FLOW3R_CTX_FLAVOUR_FULL
     if (ctx == st3m_gfx_ctx_int(st3m_gfx_osd)) {
         xSemaphoreGive(st3m_osd_lock);
-        return;
+        return 1;
     }
 #endif
     st3m_gfx_mode set_mode = _st3m_gfx_mode ? _st3m_gfx_mode : default_mode;
     if ((set_mode & st3m_gfx_smart_redraw) && (set_mode & st3m_gfx_direct_ctx))
         ctx_end_frame(ctx);
+    return 0;
+}
 
+void st3m_gfx_end_frame(Ctx *ctx) {
+    if (end_frame(ctx)) return;
     st3m_gfx_pipe_put();
 }
 
+void st3m_gfx_drop_frame(Ctx *ctx) {
+    if (end_frame(ctx)) return;
+    st3m_gfx_drawlist *drawlist = &drawlists[last_descno];
+    ctx_drawlist_clear(drawlist->user_ctx);
+    xQueueSend(user_ctx_freeq, &last_descno, portMAX_DELAY);
+}
+
 uint8_t st3m_gfx_pipe_available(void) {
     st3m_gfx_mode set_mode = _st3m_gfx_mode ? _st3m_gfx_mode : default_mode;
     if ((set_mode & st3m_gfx_EXPERIMENTAL_think_per_draw) &&
diff --git a/components/st3m/st3m_gfx.h b/components/st3m/st3m_gfx.h
index faf4883a07195bbc07766ac0b3b2c869e07643a6..7c31dd742ae8684c1b44d6cd6be34c3383fa24d9 100644
--- a/components/st3m/st3m_gfx.h
+++ b/components/st3m/st3m_gfx.h
@@ -101,6 +101,9 @@ float st3m_gfx_fps(void);
 // with ctx_end_frame()
 void st3m_gfx_end_frame(Ctx *ctx);
 
+// drop the current frame without submitting it for displaying
+void st3m_gfx_drop_frame(Ctx *ctx);
+
 // Initialize the gfx subsystem of st3m, includng the rasterization and
 // crtx/blitter pipeline.
 void st3m_gfx_init(void);