Replace displaio.Group.children with a python list

This is a first go at it, done by naive replacing of all array
operations with corresponding operations on the list. Note that
there is a lot of unnecessary type conversions, here. Also, list_pop
has been copied, because it's decalerd STATIC in py/objlist.h
This commit is contained in:
Radomir Dopieralski 2021-02-21 13:43:28 +01:00
parent 6e0ce23f3e
commit 121c6bcc9b
3 changed files with 82 additions and 73 deletions

View File

@ -33,10 +33,31 @@
#include "shared-bindings/vectorio/VectorShape.h"
#endif
#include <string.h>
#define LIST_MIN_ALLOC 4
STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {
mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
mp_obj_list_t *self = mp_instance_cast_to_native_base(args[0], &mp_type_list);
if (self->len == 0) {
mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_list);
}
size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
mp_obj_t ret = self->items[index];
self->len -= 1;
memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
// Clear stale pointer from slot which just got freed to prevent GC issues
self->items[self->len] = MP_OBJ_NULL;
if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) {
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2);
self->alloc /= 2;
}
return ret;
}
void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y) {
displayio_group_child_t* children = m_new(displayio_group_child_t, max_size);
displayio_group_construct(self, children, max_size, scale, x, y);
mp_obj_list_t *members = mp_obj_new_list(0, NULL);
displayio_group_construct(self, members, scale, x, y);
}
bool common_hal_displayio_group_get_hidden(displayio_group_t* self) {
@ -51,16 +72,16 @@ void common_hal_displayio_group_set_hidden(displayio_group_t* self, bool hidden)
if (self->hidden_by_parent) {
return;
}
for (size_t i = 0; i < self->size; i++) {
for (size_t i = 0; i < self->members->len; i++) {
mp_obj_t layer;
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
displayio_tilegrid_set_hidden_by_parent(layer, hidden);
continue;
}
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
displayio_group_set_hidden_by_parent(layer, hidden);
continue;
@ -77,16 +98,16 @@ void displayio_group_set_hidden_by_parent(displayio_group_t *self, bool hidden)
if (self->hidden) {
return;
}
for (size_t i = 0; i < self->size; i++) {
for (size_t i = 0; i < self->members->len; i++) {
mp_obj_t layer;
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
displayio_tilegrid_set_hidden_by_parent(layer, hidden);
continue;
}
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
displayio_group_set_hidden_by_parent(layer, hidden);
continue;
@ -100,18 +121,18 @@ uint32_t common_hal_displayio_group_get_scale(displayio_group_t* self) {
bool displayio_group_get_previous_area(displayio_group_t *self, displayio_area_t* area) {
bool first = true;
for (size_t i = 0; i < self->size; i++) {
for (size_t i = 0; i < self->members->len; i++) {
mp_obj_t layer;
displayio_area_t layer_area;
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
if (!displayio_tilegrid_get_previous_area(layer, &layer_area)) {
continue;
}
} else {
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
if (!displayio_group_get_previous_area(layer, &layer_area)) {
continue;
@ -140,24 +161,24 @@ static void _update_child_transforms(displayio_group_t* self) {
if (!self->in_group) {
return;
}
for (size_t i = 0; i < self->size; i++) {
for (size_t i = 0; i < self->members->len; i++) {
mp_obj_t layer;
#if CIRCUITPY_VECTORIO
layer = mp_instance_cast_to_native_base(
self->children[i].original, &vectorio_vector_shape_type);
self->members->items[i], &vectorio_vector_shape_type);
if (layer != MP_OBJ_NULL) {
vectorio_vector_shape_update_transform(layer, &self->absolute_transform);
continue;
}
#endif
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
displayio_tilegrid_update_transform(layer, &self->absolute_transform);
continue;
}
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
displayio_group_update_transform(layer, &self->absolute_transform);
continue;
@ -279,7 +300,7 @@ static void _remove_layer(displayio_group_t* self, size_t index) {
bool rendered_last_frame = false;
#if CIRCUITPY_VECTORIO
layer = mp_instance_cast_to_native_base(
self->children[index].original, &vectorio_vector_shape_type);
self->members->items[index], &vectorio_vector_shape_type);
if (layer != MP_OBJ_NULL) {
bool has_dirty_area = vectorio_vector_shape_get_dirty_area(layer, &layer_area);
rendered_last_frame = has_dirty_area;
@ -287,14 +308,14 @@ static void _remove_layer(displayio_group_t* self, size_t index) {
}
#endif
layer = mp_instance_cast_to_native_base(
self->children[index].original, &displayio_tilegrid_type);
self->members->items[index], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
displayio_tilegrid_t* tilegrid = layer;
rendered_last_frame = displayio_tilegrid_get_previous_area(tilegrid, &layer_area);
displayio_tilegrid_update_transform(tilegrid, NULL);
}
layer = mp_instance_cast_to_native_base(
self->children[index].original, &displayio_group_type);
self->members->items[index], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
displayio_group_t* group = layer;
rendered_last_frame = displayio_group_get_previous_area(group, &layer_area);
@ -312,59 +333,45 @@ static void _remove_layer(displayio_group_t* self, size_t index) {
}
void common_hal_displayio_group_insert(displayio_group_t* self, size_t index, mp_obj_t layer) {
if (self->size == self->max_size) {
mp_raise_RuntimeError(translate("Group full"));
}
_add_layer(self, layer);
// Shift everything right.
for (size_t i = self->size; i > index; i--) {
self->children[i] = self->children[i - 1];
mp_obj_list_append(self->members, mp_const_none);
for (size_t i = self->members->len - 1; i > index; i--) {
self->members->items[i] = self->members->items[i - 1];
}
self->children[index].original = layer;
self->size++;
self->members->items[index] = layer;
}
mp_obj_t common_hal_displayio_group_pop(displayio_group_t* self, size_t index) {
self->size--;
mp_obj_t item = self->children[index].original;
_remove_layer(self, index);
// Shift everything left.
for (size_t i = index; i < self->size; i++) {
self->children[i] = self->children[i + 1];
}
self->children[self->size].original = NULL;
return item;
mp_obj_t args[] = {self->members, MP_OBJ_NEW_SMALL_INT(index)};
return list_pop(2, args);
}
mp_int_t common_hal_displayio_group_index(displayio_group_t* self, mp_obj_t layer) {
for (size_t i = 0; i < self->size; i++) {
if (self->children[i].original == layer) {
return i;
}
}
return -1;
mp_obj_t args[] = {self->members, layer};
mp_obj_t *index = mp_seq_index_obj(
self->members->items, self->members->len, 2, args);
return MP_OBJ_SMALL_INT_VALUE(index);
}
size_t common_hal_displayio_group_get_len(displayio_group_t* self) {
return self->size;
return self->members->len;
}
mp_obj_t common_hal_displayio_group_get(displayio_group_t* self, size_t index) {
return self->children[index].original;
return self->members->items[index];
}
void common_hal_displayio_group_set(displayio_group_t* self, size_t index, mp_obj_t layer) {
_add_layer(self, layer);
_remove_layer(self, index);
self->children[index].original = layer;
mp_obj_list_store(self, MP_OBJ_NEW_SMALL_INT(index), layer);
}
void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y) {
void displayio_group_construct(displayio_group_t* self, mp_obj_list_t* members, uint32_t scale, mp_int_t x, mp_int_t y) {
self->x = x;
self->y = y;
self->children = child_array;
self->max_size = max_size;
self->members = members;
self->item_removed = false;
self->scale = scale;
self->in_group = false;
@ -373,11 +380,11 @@ void displayio_group_construct(displayio_group_t* self, displayio_group_child_t*
bool displayio_group_fill_area(displayio_group_t *self, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t* buffer) {
// Track if any of the layers finishes filling in the given area. We can ignore any remaining
// layers at that point.
for (int32_t i = self->size - 1; i >= 0 ; i--) {
for (int32_t i = self->members->len - 1; i >= 0 ; i--) {
mp_obj_t layer;
#if CIRCUITPY_VECTORIO
layer = mp_instance_cast_to_native_base(
self->children[i].original, &vectorio_vector_shape_type);
self->members->items[i], &vectorio_vector_shape_type);
if (layer != MP_OBJ_NULL) {
if (vectorio_vector_shape_fill_area(layer, colorspace, area, mask, buffer)) {
return true;
@ -386,7 +393,7 @@ bool displayio_group_fill_area(displayio_group_t *self, const _displayio_colorsp
}
#endif
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
if (displayio_tilegrid_fill_area(layer, colorspace, area, mask, buffer)) {
return true;
@ -394,7 +401,7 @@ bool displayio_group_fill_area(displayio_group_t *self, const _displayio_colorsp
continue;
}
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
if (displayio_group_fill_area(layer, colorspace, area, mask, buffer)) {
return true;
@ -407,24 +414,24 @@ bool displayio_group_fill_area(displayio_group_t *self, const _displayio_colorsp
void displayio_group_finish_refresh(displayio_group_t *self) {
self->item_removed = false;
for (int32_t i = self->size - 1; i >= 0 ; i--) {
for (int32_t i = self->members->len - 1; i >= 0 ; i--) {
mp_obj_t layer;
#if CIRCUITPY_VECTORIO
layer = mp_instance_cast_to_native_base(
self->children[i].original, &vectorio_vector_shape_type);
self->members->items[i], &vectorio_vector_shape_type);
if (layer != MP_OBJ_NULL) {
vectorio_vector_shape_finish_refresh(layer);
continue;
}
#endif
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
displayio_tilegrid_finish_refresh(layer);
continue;
}
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
displayio_group_finish_refresh(layer);
continue;
@ -438,24 +445,24 @@ displayio_area_t* displayio_group_get_refresh_areas(displayio_group_t *self, dis
tail = &self->dirty_area;
}
for (int32_t i = self->size - 1; i >= 0 ; i--) {
for (int32_t i = self->members->len - 1; i >= 0 ; i--) {
mp_obj_t layer;
#if CIRCUITPY_VECTORIO
layer = mp_instance_cast_to_native_base(
self->children[i].original, &vectorio_vector_shape_type);
self->members->items[i], &vectorio_vector_shape_type);
if (layer != MP_OBJ_NULL) {
tail = vectorio_vector_shape_get_refresh_areas(layer, tail);
continue;
}
#endif
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_tilegrid_type);
self->members->items[i], &displayio_tilegrid_type);
if (layer != MP_OBJ_NULL) {
tail = displayio_tilegrid_get_refresh_areas(layer, tail);
continue;
}
layer = mp_instance_cast_to_native_base(
self->children[i].original, &displayio_group_type);
self->members->items[i], &displayio_group_type);
if (layer != MP_OBJ_NULL) {
tail = displayio_group_get_refresh_areas(layer, tail);
continue;

View File

@ -31,6 +31,7 @@
#include <stdint.h>
#include "py/obj.h"
#include "py/objlist.h"
#include "shared-module/displayio/area.h"
#include "shared-module/displayio/Palette.h"
@ -40,14 +41,12 @@ typedef struct {
typedef struct {
mp_obj_base_t base;
displayio_group_child_t* children;
mp_obj_list_t *members;
displayio_buffer_transform_t absolute_transform;
displayio_area_t dirty_area; // Catch all for changed area
int16_t x;
int16_t y;
uint16_t scale;
uint16_t size;
uint16_t max_size;
bool item_removed :1;
bool in_group :1;
bool hidden :1;
@ -55,7 +54,7 @@ typedef struct {
uint8_t padding :4;
} displayio_group_t;
void displayio_group_construct(displayio_group_t* self, displayio_group_child_t* child_array, uint32_t max_size, uint32_t scale, mp_int_t x, mp_int_t y);
void displayio_group_construct(displayio_group_t* self, mp_obj_list_t* members, uint32_t scale, mp_int_t x, mp_int_t y);
void displayio_group_set_hidden_by_parent(displayio_group_t *self, bool hidden);
bool displayio_group_get_previous_area(displayio_group_t *group, displayio_area_t* area);
bool displayio_group_fill_area(displayio_group_t *group, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer);

View File

@ -270,15 +270,20 @@ displayio_tilegrid_t blinka_sprite = {
};
#if CIRCUITPY_TERMINALIO
#define CHILD_COUNT 2
displayio_group_child_t splash_children[2] = {
{&blinka_sprite},
{&supervisor_terminal_text_grid},
mp_obj_t members[] = { &blinka_sprite, &supervisor_terminal_text_grid, };
mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list },
.alloc = 2,
.len = 2,
.items = members,
};
#else
#define CHILD_COUNT 1
displayio_group_child_t splash_children[1] = {
{&blinka_sprite},
mp_obj_t members[] = { &blinka_sprite };
mp_obj_list_t splash_children = {
.base = {.type = &mp_type_list },
.alloc = 1,
.len = 1,
.items = members,
};
#endif
@ -287,9 +292,7 @@ displayio_group_t circuitpython_splash = {
.x = 0,
.y = 0,
.scale = 2,
.size = CHILD_COUNT,
.max_size = CHILD_COUNT,
.children = splash_children,
.members = &splash_children,
.item_removed = false,
.in_group = false,
.hidden = false,