2424
2525#if CIRCUITPY_OS_GETENV && CIRCUITPY_SET_DISPLAY_LIMIT
2626#include "shared-module/os/__init__.h"
27+ #include "py/misc.h"
2728#endif
2829
2930#if CIRCUITPY_BUSDISPLAY
5152// The default indicates no primary display
5253static int primary_display_number = -1 ;
5354static mp_int_t max_num_displays = CIRCUITPY_DISPLAY_LIMIT ;
55+ mp_int_t max_allocated_display = CIRCUITPY_DISPLAY_LIMIT ;
5456
5557primary_display_bus_t display_buses [CIRCUITPY_DISPLAY_LIMIT ];
5658primary_display_t displays [CIRCUITPY_DISPLAY_LIMIT ];
@@ -87,7 +89,7 @@ displayio_buffer_transform_t null_transform = {
8789
8890#if CIRCUITPY_RGBMATRIX || CIRCUITPY_IS31FL3741 || CIRCUITPY_VIDEOCORE || CIRCUITPY_PICODVI
8991static bool any_display_uses_this_framebuffer (mp_obj_base_t * obj ) {
90- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
92+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
9193 if (DYN_DISPLAYS (i ).display_base .type == & framebufferio_framebufferdisplay_type ) {
9294 framebufferio_framebufferdisplay_obj_t * display = DYN_DISPLAYS_ADR (i , framebuffer_display );
9395 if (display -> framebuffer == obj ) {
@@ -109,7 +111,7 @@ void displayio_background(void) {
109111 return ;
110112 }
111113
112- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
114+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
113115 mp_const_obj_t display_type = DYN_DISPLAYS (i ).display_base .type ;
114116 if (display_type == NULL || display_type == & mp_type_NoneType ) {
115117 // Skip null display.
@@ -139,7 +141,7 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) {
139141 if (!keep_primary ) {
140142 primary_display_number = -1 ;
141143 }
142- for (uint8_t i = (keep_primary ? CIRCUITPY_DISPLAY_LIMIT : 0 ); i < max_num_displays ; i ++ ) {
144+ for (uint8_t i = (keep_primary ? CIRCUITPY_DISPLAY_LIMIT : 0 ); i < max_allocated_display ; i ++ ) {
143145 if (i == primary_display_number ) {
144146 continue ;
145147 }
@@ -169,7 +171,7 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) {
169171 displays [i ].display_base .type = & mp_type_NoneType ;
170172 #endif
171173 }
172- for (uint8_t i = (keep_primary ? CIRCUITPY_DISPLAY_LIMIT : 0 ); i < max_num_displays ; i ++ ) {
174+ for (uint8_t i = (keep_primary ? CIRCUITPY_DISPLAY_LIMIT : 0 ); i < max_allocated_display ; i ++ ) {
173175 if (i == primary_display_number ) {
174176 continue ;
175177 }
@@ -237,15 +239,14 @@ void malloc_display_memory(void) {
237239 #if CIRCUITPY_OS_GETENV && CIRCUITPY_SET_DISPLAY_LIMIT
238240 (void )common_hal_os_getenv_int ("CIRCUITPY_DISPLAY_LIMIT" , & max_num_displays );
239241 if (max_num_displays > CIRCUITPY_DISPLAY_LIMIT ) {
240- display_buses_dyn = (primary_display_bus_t * ) port_malloc ( sizeof ( primary_display_bus_t ) * ( max_num_displays - CIRCUITPY_DISPLAY_LIMIT ), false );
241- displays_dyn = (primary_display_t * ) port_malloc ( sizeof ( primary_display_t ) * ( max_num_displays - CIRCUITPY_DISPLAY_LIMIT ), false );
242+ display_buses_dyn = m_new0 (primary_display_bus_t , ( max_num_displays - CIRCUITPY_DISPLAY_LIMIT ));
243+ displays_dyn = m_new0 (primary_display_t , ( max_num_displays - CIRCUITPY_DISPLAY_LIMIT ));
242244
243245 for (uint8_t i = CIRCUITPY_DISPLAY_LIMIT ; i < max_num_displays ; i ++ ) {
244- memset (& displays_dyn [i - CIRCUITPY_DISPLAY_LIMIT ], 0 , sizeof (displays_dyn [i - CIRCUITPY_DISPLAY_LIMIT ]));
245- memset (& display_buses_dyn [i - CIRCUITPY_DISPLAY_LIMIT ], 0 , sizeof (display_buses_dyn [i - CIRCUITPY_DISPLAY_LIMIT ]));
246246 display_buses_dyn [i - CIRCUITPY_DISPLAY_LIMIT ].bus_base .type = & mp_type_NoneType ;
247247 displays_dyn [i - CIRCUITPY_DISPLAY_LIMIT ].display_base .type = & mp_type_NoneType ;
248248 }
249+ max_allocated_display = max_num_displays ;
249250 }
250251 #endif
251252}
@@ -418,7 +419,7 @@ void reset_displays(void) {
418419}
419420
420421void displayio_gc_collect (void ) {
421- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
422+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
422423 mp_const_obj_t display_bus_type = DYN_DISPLAY_BUSES (i ).bus_base .type ;
423424 if (display_bus_type == NULL || display_bus_type == & mp_type_NoneType ) {
424425 continue ;
@@ -445,7 +446,7 @@ void displayio_gc_collect(void) {
445446 #endif
446447 }
447448
448- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
449+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
449450 mp_const_obj_t display_type = DYN_DISPLAYS (i ).display_base .type ;
450451 if (display_type == NULL || display_type == & mp_type_NoneType ) {
451452 continue ;
@@ -473,7 +474,7 @@ static bool is_display_active(mp_obj_base_t *display_maybe) {
473474}
474475
475476primary_display_t * allocate_display (void ) {
476- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
477+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
477478 if (!is_display_active (DYN_DISPLAYS_ADR (i , display_base ))) {
478479 // Clear this memory so it is in a known state before init.
479480 memset (DYN_DISPLAYS_ADR0 (i ), 0 , sizeof (displays [0 ]));
@@ -490,6 +491,14 @@ primary_display_t *allocate_display(void) {
490491 return DYN_DISPLAYS_ADR0 (i );
491492 }
492493 }
494+ #if CIRCUITPY_OS_GETENV && CIRCUITPY_SET_DISPLAY_LIMIT
495+ // malloc_display_memory allocates both displays and buses
496+ if (max_allocated_display == CIRCUITPY_DISPLAY_LIMIT ) {
497+ // See if we can allocate more displays and buses
498+ malloc_display_memory ();
499+ return & displays_dyn [0 ];
500+ }
501+ #endif
493502 return NULL ;
494503}
495504
@@ -502,7 +511,7 @@ primary_display_t *allocate_display_or_raise(void) {
502511}
503512
504513primary_display_bus_t * allocate_display_bus (void ) {
505- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
514+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
506515 mp_const_obj_t display_bus_type = DYN_DISPLAY_BUSES (i ).bus_base .type ;
507516 if (display_bus_type == NULL || display_bus_type == & mp_type_NoneType ) {
508517 // Clear this memory so it is in a known state before init.
@@ -519,6 +528,14 @@ primary_display_bus_t *allocate_display_bus(void) {
519528 return DYN_DISPLAY_BUSES_ADR0 (i );
520529 }
521530 }
531+ #if CIRCUITPY_OS_GETENV && CIRCUITPY_SET_DISPLAY_LIMIT
532+ // malloc_display_memory allocates both displays and buses
533+ if (max_allocated_display == CIRCUITPY_DISPLAY_LIMIT ) {
534+ // See if e can allocate more displays and buses
535+ malloc_display_memory ();
536+ return & display_buses_dyn [0 ];
537+ }
538+ #endif
522539 return NULL ;
523540}
524541
@@ -531,7 +548,7 @@ primary_display_bus_t *allocate_display_bus_or_raise(void) {
531548}
532549
533550mp_obj_t common_hal_displayio_get_primary_display (void ) {
534- if (primary_display_number == -1 || primary_display_number >= max_num_displays ) {
551+ if (primary_display_number == -1 || primary_display_number >= max_allocated_display ) {
535552 return mp_const_none ;
536553 }
537554 mp_obj_base_t * primary_display = DYN_DISPLAYS_ADR (primary_display_number , display_base );
@@ -546,7 +563,7 @@ void common_hal_displayio_set_primary_display(mp_obj_t new_primary_display) {
546563 primary_display_number = -1 ;
547564 return ;
548565 }
549- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
566+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
550567 mp_obj_t display = MP_OBJ_FROM_PTR (DYN_DISPLAYS_ADR0 (i ));
551568 if (new_primary_display == display && is_display_active (display )) {
552569 primary_display_number = i ;
@@ -561,7 +578,7 @@ void common_hal_displayio_auto_primary_display(void) {
561578 if (primary_display_number != -1 ) {
562579 return ;
563580 }
564- for (uint8_t i = 0 ; i < max_num_displays ; i ++ ) {
581+ for (uint8_t i = 0 ; i < max_allocated_display ; i ++ ) {
565582 if (is_display_active (DYN_DISPLAYS_ADR (i , display_base ))) {
566583 primary_display_number = i ;
567584 return ;
0 commit comments