From 6e3fc9aca8109995f2158b4ec07d73343a649388 Mon Sep 17 00:00:00 2001
From: b0xcat <me@b0xcat.nl>
Date: Tue, 5 May 2026 22:06:53 +0200
Subject: [PATCH 3/5] Add partial blit support to flow3r gc9a01 code

---
 components/flow3r_bsp/flow3r_bsp.h         |  6 ++++++
 components/flow3r_bsp/flow3r_bsp_display.c | 10 ++++++++++
 components/flow3r_bsp/flow3r_bsp_gc9a01.c  | 20 ++++++++++++++++++++
 components/flow3r_bsp/flow3r_bsp_gc9a01.h  |  9 +++++++++
 4 files changed, 45 insertions(+)

diff --git a/components/flow3r_bsp/flow3r_bsp.h b/components/flow3r_bsp/flow3r_bsp.h
index bdfb1c4..5aed7b1 100644
--- a/components/flow3r_bsp/flow3r_bsp.h
+++ b/components/flow3r_bsp/flow3r_bsp.h
@@ -27,6 +27,12 @@ void flow3r_bsp_display_send_fb_osd(void *fb_data, int bits, int scale,
                                     void *osd_data, int osd_x0, int osd_y0,
                                     int osd_x1, int osd_y1);
 
+// Send pre-rendered pixel data to a rectangular region of the display.
+// Data is w*h pixels of 16bpp RGB565 byteswapped, contiguous row-major.
+void flow3r_bsp_display_send_rect(const void *data,
+                                   uint16_t x, uint16_t y,
+                                   uint16_t w, uint16_t h);
+
 // Set display backlight, as integer percent value (from 0 to 100, clamped).
 // No-op if display hasn't been successfully initialized.
 void flow3r_bsp_display_set_backlight(uint8_t percent);
diff --git a/components/flow3r_bsp/flow3r_bsp_display.c b/components/flow3r_bsp/flow3r_bsp_display.c
index 29ebc59..c38f8a8 100644
--- a/components/flow3r_bsp/flow3r_bsp_display.c
+++ b/components/flow3r_bsp/flow3r_bsp_display.c
@@ -64,6 +64,16 @@ void flow3r_bsp_display_send_fb(void *fb_data, int bits) {
     flow3r_bsp_display_send_fb_osd(fb_data, bits, 1, NULL, 0, 0, 0, 0);
 }
 
+void flow3r_bsp_display_send_rect(const void *data,
+                                   uint16_t x, uint16_t y,
+                                   uint16_t w, uint16_t h) {
+    if (!gc9a01_initialized) return;
+    esp_err_t ret = flow3r_bsp_gc9a01_blit_rect(&gc9a01, data, x, y, w, h);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "display rect blit failed: %s", esp_err_to_name(ret));
+    }
+}
+
 void flow3r_bsp_display_set_backlight(uint8_t percent) {
     if (!gc9a01_initialized) {
         return;
diff --git a/components/flow3r_bsp/flow3r_bsp_gc9a01.c b/components/flow3r_bsp/flow3r_bsp_gc9a01.c
index 3616391..98b0de6 100644
--- a/components/flow3r_bsp/flow3r_bsp_gc9a01.c
+++ b/components/flow3r_bsp/flow3r_bsp_gc9a01.c
@@ -1096,3 +1096,23 @@ esp_err_t flow3r_bsp_gc9a01_blit_full(flow3r_bsp_gc9a01_t *gc9a01,
                                       const void *fb, int bits) {
     return flow3r_bsp_gc9a01_blit_osd(gc9a01, fb, bits, 1, NULL, 0, 0, 0, 0);
 }
+
+esp_err_t flow3r_bsp_gc9a01_blit_rect(flow3r_bsp_gc9a01_t *gc9a01,
+                                       const void *data,
+                                       uint16_t x, uint16_t y,
+                                       uint16_t w, uint16_t h) {
+    if (x >= 240 || y >= 240 || w == 0 || h == 0) return ESP_OK;
+    if (x + w > 240) w = 240 - x;
+    if (y + h > 240) h = 240 - y;
+
+    esp_err_t ret;
+    ret = flow3r_bsp_gc9a01_column_set(gc9a01, x, x + w - 1);
+    if (ret != ESP_OK) return ret;
+    ret = flow3r_bsp_gc9a01_row_set(gc9a01, y, y + h - 1);
+    if (ret != ESP_OK) return ret;
+    ret = flow3r_bsp_gc9a01_cmd_sync(gc9a01, Cmd_RAMWR);
+    if (ret != ESP_OK) return ret;
+    ret = flow3r_bsp_gc9a01_data_sync(gc9a01, data, w * h * 2);
+
+    return ret;
+}
diff --git a/components/flow3r_bsp/flow3r_bsp_gc9a01.h b/components/flow3r_bsp/flow3r_bsp_gc9a01.h
index 28ed0cb..d142f5a 100644
--- a/components/flow3r_bsp/flow3r_bsp_gc9a01.h
+++ b/components/flow3r_bsp/flow3r_bsp_gc9a01.h
@@ -74,6 +74,15 @@ esp_err_t flow3r_bsp_gc9a01_blit_osd(flow3r_bsp_gc9a01_t *gc9a01,
                                      const void *osd_fb, int osd_x0, int osd_y0,
                                      int osd_x1, int osd_y1);
 
+// Send pre-rendered pixel data to a rectangular region of the display.
+// Data must be w*h pixels in 16bpp RGB565 byteswapped format, packed
+// contiguously (row-major, no stride gaps).
+// Coordinates are clamped to display bounds.
+esp_err_t flow3r_bsp_gc9a01_blit_rect(flow3r_bsp_gc9a01_t *gc9a01,
+                                       const void *data,
+                                       uint16_t x, uint16_t y,
+                                       uint16_t w, uint16_t h);
+
 // Set backlight for display, using integer percent value (0-100, clamped).
 esp_err_t flow3r_bsp_gc9a01_backlight_set(flow3r_bsp_gc9a01_t *gc9a01,
                                           uint8_t value);
-- 
2.53.0

