@@ -233,6 +233,7 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
233233 return true;
234234 }
235235 uint16_t rows_per_buffer = displayio_area_height (& clipped );
236+ uint16_t cols_per_buffer = displayio_area_width (& clipped );
236237 uint8_t pixels_per_word = (sizeof (uint32_t ) * 8 ) / self -> core .colorspace .depth ;
237238 uint16_t pixels_per_buffer = displayio_area_size (& clipped );
238239
@@ -243,26 +244,29 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
243244 subrectangles = rows_per_buffer / 8 ; // page addressing mode writes 8 rows at a time
244245 rows_per_buffer = 8 ;
245246 } else if (displayio_area_size (& clipped ) > buffer_size * pixels_per_word ) {
246- rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width (& clipped );
247- if (rows_per_buffer == 0 ) {
248- rows_per_buffer = 1 ;
249- }
250- // If pixels are packed by column then ensure rows_per_buffer is on a byte boundary.
251- if (self -> core .colorspace .depth < 8 && !self -> core .colorspace .pixels_in_byte_share_row ) {
252- uint8_t pixels_per_byte = 8 / self -> core .colorspace .depth ;
253- if (rows_per_buffer % pixels_per_byte != 0 ) {
254- rows_per_buffer -= rows_per_buffer % pixels_per_byte ;
247+ uint16_t buffer_pixels = buffer_size * pixels_per_word ;
248+ if (self -> core .transform .transpose_xy && self -> core .colorspace .depth >= 8 ) {
249+ // Rotated 90 or 270: a panel column is a source row. Send bands of columns so sources
250+ // are read along their rows, which OnDiskBitmap needs to avoid a file seek per pixel.
251+ rows_per_buffer = MIN (rows_per_buffer , buffer_pixels );
252+ cols_per_buffer = buffer_pixels / rows_per_buffer ;
253+ } else {
254+ rows_per_buffer = buffer_pixels / cols_per_buffer ;
255+ if (rows_per_buffer == 0 ) {
256+ rows_per_buffer = 1 ;
257+ }
258+ // If pixels are packed by column then ensure rows_per_buffer is on a byte boundary.
259+ if (self -> core .colorspace .depth < 8 && !self -> core .colorspace .pixels_in_byte_share_row ) {
260+ uint8_t pixels_per_byte = 8 / self -> core .colorspace .depth ;
261+ if (rows_per_buffer % pixels_per_byte != 0 ) {
262+ rows_per_buffer -= rows_per_buffer % pixels_per_byte ;
263+ }
255264 }
256265 }
257- subrectangles = displayio_area_height (& clipped ) / rows_per_buffer ;
258- if (displayio_area_height (& clipped ) % rows_per_buffer != 0 ) {
259- subrectangles ++ ;
260- }
261- pixels_per_buffer = rows_per_buffer * displayio_area_width (& clipped );
262- buffer_size = pixels_per_buffer / pixels_per_word ;
263- if (pixels_per_buffer % pixels_per_word ) {
264- buffer_size += 1 ;
265- }
266+ subrectangles = ((displayio_area_height (& clipped ) + rows_per_buffer - 1 ) / rows_per_buffer ) *
267+ ((displayio_area_width (& clipped ) + cols_per_buffer - 1 ) / cols_per_buffer );
268+ pixels_per_buffer = rows_per_buffer * cols_per_buffer ;
269+ buffer_size = (pixels_per_buffer + pixels_per_word - 1 ) / pixels_per_word ;
266270 }
267271
268272 // Allocated and shared as a uint32_t array so the compiler knows the
@@ -271,19 +275,17 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
271275 uint32_t buffer [buffer_size ];
272276 uint32_t mask [mask_length ];
273277
274- uint16_t remaining_rows = displayio_area_height (& clipped );
278+ displayio_area_t subrectangle = clipped ;
279+ subrectangle .next = NULL ;
275280
276281 for (uint16_t j = 0 ; j < subrectangles ; j ++ ) {
277- displayio_area_t subrectangle = {
278- .x1 = clipped .x1 ,
279- .y1 = clipped .y1 + rows_per_buffer * j ,
280- .x2 = clipped .x2 ,
281- .y2 = clipped .y1 + rows_per_buffer * (j + 1 )
282- };
283- if (remaining_rows < rows_per_buffer ) {
284- subrectangle .y2 = subrectangle .y1 + remaining_rows ;
282+ // Down the rows of a band first, then to the next band of columns.
283+ if (subrectangle .y1 >= clipped .y2 ) {
284+ subrectangle .y1 = clipped .y1 ;
285+ subrectangle .x1 += cols_per_buffer ;
285286 }
286- remaining_rows -= rows_per_buffer ;
287+ subrectangle .x2 = MIN (subrectangle .x1 + cols_per_buffer , clipped .x2 );
288+ subrectangle .y2 = MIN (subrectangle .y1 + rows_per_buffer , clipped .y2 );
287289
288290 uint16_t subrectangle_size_bytes ;
289291 if (self -> core .colorspace .depth >= 8 ) {
@@ -305,6 +307,7 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are
305307 }
306308 _send_pixels (self , (uint8_t * )buffer , subrectangle_size_bytes );
307309 displayio_display_bus_end_transaction (& self -> bus );
310+ subrectangle .y1 = subrectangle .y2 ;
308311
309312 // Run background tasks so they can run during an explicit refresh.
310313 // Auto-refresh won't run background tasks here because it is a background task itself.
0 commit comments