Skip to content

Commit 6f71216

Browse files
committed
displayio: make region command sends reusable for QSPI transactions
Refactor display bus region-update command emission into a shared helper with optional transaction management. Keep the existing public path unchanged, and add a QSPIBus-only entrypoint that can send region commands without nesting begin/end transaction calls. Also remove the TileGrid 16bpp+Palette fast path so fill_area uses the generic path, and fix indentation in QSPIBus write_data.
1 parent 39862f3 commit 6f71216

File tree

3 files changed

+36
-79
lines changed

3 files changed

+36
-79
lines changed

ports/espressif/common-hal/qspibus/QSPIBus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ void common_hal_qspibus_qspibus_write_data(
464464
}
465465
return;
466466
}
467-
if (!self->has_pending_command) {
467+
if (!self->has_pending_command) {
468468
mp_raise_ValueError(MP_ERROR_TEXT("No pending command"));
469469
}
470470

shared-module/displayio/TileGrid.c

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -512,75 +512,6 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self,
512512
y_shift = temp_shift;
513513
}
514514

515-
// Fast path for the common case: single-tile, 16bpp bitmap with Palette,
516-
// no transforms, full coverage. Inlines bitmap access and palette cache
517-
// lookup to eliminate per-pixel function-call overhead (~4-5x speedup).
518-
if (full_coverage &&
519-
colorspace->depth == 16 &&
520-
self->width_in_tiles == 1 &&
521-
self->height_in_tiles == 1 &&
522-
self->absolute_transform->scale == 1 &&
523-
self->absolute_transform->dx == 1 &&
524-
self->absolute_transform->dy == 1 &&
525-
!self->absolute_transform->transpose_xy &&
526-
!self->flip_x && !self->flip_y &&
527-
!self->transpose_xy &&
528-
x_stride == 1 && y_stride == displayio_area_width(area) &&
529-
x_shift == 0 && y_shift == 0 &&
530-
mp_obj_is_type(self->bitmap, &displayio_bitmap_type) &&
531-
mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) {
532-
533-
displayio_bitmap_t *bmp = MP_OBJ_TO_PTR(self->bitmap);
534-
displayio_palette_t *pal = MP_OBJ_TO_PTR(self->pixel_shader);
535-
536-
if (bmp->bits_per_value == 16 && !pal->dither) {
537-
uint16_t *out = (uint16_t *)buffer;
538-
bool all_opaque = true;
539-
540-
// Process all pixels with inlined bitmap access and palette cache.
541-
uint32_t idx = 0;
542-
for (int16_t y = start_y; y < end_y; ++y) {
543-
// Direct row pointer into bitmap data (16bpp → uint16_t).
544-
// stride is in uint32_t units, so multiply by 2 for uint16_t indexing.
545-
const uint16_t *bmp_row = ((const uint16_t *)bmp->data) + y * (bmp->stride * 2);
546-
547-
for (int16_t x = start_x; x < end_x; ++x) {
548-
uint16_t px_index = bmp_row[x];
549-
550-
// Inline palette cache check (avoids function call overhead).
551-
if (px_index < pal->color_count) {
552-
_displayio_color_t *color = &pal->colors[px_index];
553-
if (color->transparent) {
554-
all_opaque = false;
555-
idx++;
556-
continue;
557-
}
558-
if (color->cached_colorspace == colorspace &&
559-
color->cached_colorspace_grayscale_bit == colorspace->grayscale_bit &&
560-
color->cached_colorspace_grayscale == colorspace->grayscale) {
561-
out[idx] = (uint16_t)color->cached_color;
562-
} else {
563-
// Cache miss — do full conversion, then cache.
564-
displayio_input_pixel_t in_px = {.pixel = px_index};
565-
displayio_output_pixel_t out_px = {.opaque = true};
566-
displayio_palette_get_color(pal, colorspace, &in_px, &out_px);
567-
out[idx] = (uint16_t)out_px.pixel;
568-
}
569-
} else {
570-
// Out of palette range — transparent.
571-
all_opaque = false;
572-
idx++;
573-
continue;
574-
}
575-
mask[idx >> 5] |= 1u << (idx & 31);
576-
idx++;
577-
}
578-
}
579-
580-
return all_opaque;
581-
}
582-
}
583-
584515
displayio_input_pixel_t input_pixel;
585516
displayio_output_pixel_t output_pixel;
586517

shared-module/displayio/bus_core.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void displayio_display_bus_end_transaction(displayio_display_bus_t *self) {
114114
self->end_transaction(self->bus);
115115
}
116116

117-
void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area) {
117+
static void _displayio_display_bus_send_region_commands(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area, bool manage_transactions) {
118118
uint16_t x1 = area->x1 + self->colstart;
119119
uint16_t x2 = area->x2 + self->colstart;
120120
uint16_t y1 = area->y1 + self->rowstart;
@@ -141,7 +141,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d
141141
}
142142

143143
// Set column.
144-
displayio_display_bus_begin_transaction(self);
144+
if (manage_transactions) {
145+
displayio_display_bus_begin_transaction(self);
146+
}
145147
uint8_t data[5];
146148
data[0] = self->column_command;
147149
uint8_t data_length = 1;
@@ -176,20 +178,28 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d
176178
}
177179

178180
self->send(self->bus, data_type, chip_select, data, data_length);
179-
displayio_display_bus_end_transaction(self);
181+
if (manage_transactions) {
182+
displayio_display_bus_end_transaction(self);
183+
}
180184

181185
if (self->set_current_column_command != NO_COMMAND) {
182186
uint8_t command = self->set_current_column_command;
183-
displayio_display_bus_begin_transaction(self);
187+
if (manage_transactions) {
188+
displayio_display_bus_begin_transaction(self);
189+
}
184190
self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1);
185191
// Only send the first half of data because it is the first coordinate.
186192
self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2);
187-
displayio_display_bus_end_transaction(self);
193+
if (manage_transactions) {
194+
displayio_display_bus_end_transaction(self);
195+
}
188196
}
189197

190198

191199
// Set row.
192-
displayio_display_bus_begin_transaction(self);
200+
if (manage_transactions) {
201+
displayio_display_bus_begin_transaction(self);
202+
}
193203
data[0] = self->row_command;
194204
data_length = 1;
195205
if (!self->data_as_commands) {
@@ -220,18 +230,34 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d
220230
}
221231

222232
self->send(self->bus, data_type, chip_select, data, data_length);
223-
displayio_display_bus_end_transaction(self);
233+
if (manage_transactions) {
234+
displayio_display_bus_end_transaction(self);
235+
}
224236

225237
if (self->set_current_row_command != NO_COMMAND) {
226238
uint8_t command = self->set_current_row_command;
227-
displayio_display_bus_begin_transaction(self);
239+
if (manage_transactions) {
240+
displayio_display_bus_begin_transaction(self);
241+
}
228242
self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1);
229243
// Only send the first half of data because it is the first coordinate.
230244
self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2);
231-
displayio_display_bus_end_transaction(self);
245+
if (manage_transactions) {
246+
displayio_display_bus_end_transaction(self);
247+
}
232248
}
233249
}
234250

251+
void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area) {
252+
_displayio_display_bus_send_region_commands(self, display, area, true);
253+
}
254+
255+
#if CIRCUITPY_QSPIBUS
256+
void displayio_display_bus_send_region_commands(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area) {
257+
_displayio_display_bus_send_region_commands(self, display, area, false);
258+
}
259+
#endif
260+
235261
void displayio_display_bus_collect_ptrs(displayio_display_bus_t *self) {
236262
self->collect_ptrs(self->bus);
237263
}

0 commit comments

Comments
 (0)