Skip to content

TilePaletteMapper support for ColorConverter #10173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions shared-bindings/tilepalettemapper/TilePaletteMapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "py/runtime.h"
#include "shared-bindings/util.h"
#include "shared-bindings/displayio/Palette.h"
#include "shared-bindings/displayio/ColorConverter.h"
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"

//| class TilePaletteMapper:
Expand All @@ -24,28 +25,29 @@
//| ) -> None:
//| """Create a TilePaletteMApper object to store a set of color mappings for tiles.
//|
//| :param displayio.Palette palette: The palette to get mapped colors from.
//| :param Union[displayio.Palette, displayio.ColorConverter] pixel_shader:
//| The palette or ColorConverter to get mapped colors from.
//| :param int input_color_count: The number of colors in in the input bitmap.
//| :param int width: The width of the grid in tiles.
//| :param int height: The height of the grid in tiles."""
//|

static mp_obj_t tilepalettemapper_tilepalettemapper_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_palette, ARG_input_color_count, ARG_width, ARG_height };
enum { ARG_pixel_shader, ARG_input_color_count, ARG_width, ARG_height };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_palette, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_input_color_count, MP_ARG_INT | MP_ARG_REQUIRED },
{ MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED },
{ MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_obj_t palette = args[ARG_palette].u_obj;
if (!mp_obj_is_type(palette, &displayio_palette_type)) {
mp_obj_t pixel_shader = args[ARG_pixel_shader].u_obj;
if (!mp_obj_is_type(pixel_shader, &displayio_palette_type) && !mp_obj_is_type(pixel_shader, &displayio_colorconverter_type)) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader);
}
tilepalettemapper_tilepalettemapper_t *self = mp_obj_malloc(tilepalettemapper_tilepalettemapper_t, &tilepalettemapper_tilepalettemapper_type);
common_hal_tilepalettemapper_tilepalettemapper_construct(self, palette, args[ARG_input_color_count].u_int, args[ARG_width].u_int, args[ARG_height].u_int);
common_hal_tilepalettemapper_tilepalettemapper_construct(self, pixel_shader, args[ARG_input_color_count].u_int, args[ARG_width].u_int, args[ARG_height].u_int);

return MP_OBJ_FROM_PTR(self);
}
Expand Down Expand Up @@ -73,17 +75,17 @@ MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_height_obj,
(mp_obj_t)&tilepalettemapper_tilepalettemapper_get_height_obj);


//| palette: displayio.Palette
//| """The palette that the mapper uses."""
//| pixel_shader: Union[displayio.Palette, displayio.ColorConverter]
//| """The palette or ColorConverter that the mapper uses."""
//|
static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_palette(mp_obj_t self_in) {
static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_pixel_shader(mp_obj_t self_in) {
tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in);
return common_hal_tilepalettemapper_tilepalettemapper_get_palette(self);
return common_hal_tilepalettemapper_tilepalettemapper_get_pixel_shader(self);
}
MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_palette_obj, tilepalettemapper_tilepalettemapper_obj_get_palette);
MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_pixel_shader_obj, tilepalettemapper_tilepalettemapper_obj_get_pixel_shader);

MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_palette_obj,
(mp_obj_t)&tilepalettemapper_tilepalettemapper_get_palette_obj);
(mp_obj_t)&tilepalettemapper_tilepalettemapper_get_pixel_shader_obj);


//| def __getitem__(self, index: Union[Tuple[int, int], int]) -> Tuple[int]:
Expand Down
2 changes: 1 addition & 1 deletion shared-bindings/tilepalettemapper/TilePaletteMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_

uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_width(tilepalettemapper_tilepalettemapper_t *self);
uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_height(tilepalettemapper_tilepalettemapper_t *self);
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_palette(tilepalettemapper_tilepalettemapper_t *self);
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_pixel_shader(tilepalettemapper_tilepalettemapper_t *self);
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y);
void common_hal_tilepalettemapper_tilepalettemapper_set_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y, size_t len, mp_obj_t *items);
46 changes: 34 additions & 12 deletions shared-module/tilepalettemapper/TilePaletteMapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,28 @@
#include "py/runtime.h"
#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h"
#include "shared-bindings/displayio/Palette.h"
#include "shared-bindings/displayio/ColorConverter.h"

void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_tilepalettemapper_t *self,
mp_obj_t palette, uint16_t input_color_count, uint16_t width, uint16_t height) {
mp_obj_t pixel_shader, uint16_t input_color_count, uint16_t width, uint16_t height) {

self->palette = palette;
self->pixel_shader = pixel_shader;
self->width_in_tiles = width;
self->height_in_tiles = height;
self->input_color_count = input_color_count;
self->needs_refresh = false;
int mappings_len = width * height;
self->tile_mappings = (uint16_t **)m_malloc(mappings_len * sizeof(uint16_t *));
self->tile_mappings = (uint32_t **)m_malloc(mappings_len * sizeof(uint32_t *));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to make this smarter in the future to scale the output values depending on the pixel shader. uint32_t for CC. uint8_t for small palettes and uint16_t for larger ones.

for (int i = 0; i < mappings_len; i++) {
self->tile_mappings[i] = (uint16_t *)m_malloc(input_color_count * sizeof(uint16_t));
for (uint16_t j = 0; j < input_color_count; j++) {
self->tile_mappings[i][j] = j;
self->tile_mappings[i] = (uint32_t *)m_malloc(input_color_count * sizeof(uint32_t));
if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) {
for (uint16_t j = 0; j < input_color_count; j++) {
self->tile_mappings[i][j] = j;
}
} else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) {
for (uint16_t j = 0; j < input_color_count; j++) {
self->tile_mappings[i][j] = 0;
}
}
}
}
Expand All @@ -34,8 +41,8 @@ uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_height(tilepalettema
return self->height_in_tiles;
}

mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_palette(tilepalettemapper_tilepalettemapper_t *self) {
return self->palette;
mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_pixel_shader(tilepalettemapper_tilepalettemapper_t *self) {
return self->pixel_shader;
}

mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y) {
Expand All @@ -48,25 +55,40 @@ mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettem
}

void common_hal_tilepalettemapper_tilepalettemapper_set_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y, size_t len, mp_obj_t *items) {
uint32_t palette_len = common_hal_displayio_palette_get_len(self->palette);
uint32_t palette_max;
if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) {
palette_max = common_hal_displayio_palette_get_len(self->pixel_shader) - 1;
} else { // colorconverter type
palette_max = 0xFFFFFF;
}

for (uint16_t i = 0; i < MIN(len, self->input_color_count); i++) {
int mapping_val = mp_arg_validate_type_int(items[i], MP_QSTR_mapping_value);
mp_arg_validate_int_range(mapping_val, 0, palette_len - 1, MP_QSTR_mapping_value);
mp_arg_validate_int_range(mapping_val, 0, palette_max, MP_QSTR_mapping_value);
self->tile_mappings[y * self->width_in_tiles + x][i] = mapping_val;
}
self->needs_refresh = true;
}

void tilepalettemapper_tilepalettemapper_get_color(tilepalettemapper_tilepalettemapper_t *self, const _displayio_colorspace_t *colorspace, displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color, uint16_t x_tile_index, uint16_t y_tile_index) {
if (x_tile_index >= self->width_in_tiles || y_tile_index >= self->height_in_tiles) {
displayio_palette_get_color(self->palette, colorspace, input_pixel, output_color);
if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) {
displayio_palette_get_color(self->pixel_shader, colorspace, input_pixel, output_color);
} else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) {
displayio_colorconverter_convert(self->pixel_shader, colorspace, input_pixel, output_color);
}
return;
}
uint16_t tile_index = y_tile_index * self->width_in_tiles + x_tile_index;
uint32_t mapped_index = self->tile_mappings[tile_index][input_pixel->pixel];
displayio_input_pixel_t tmp_pixel;
tmp_pixel.pixel = mapped_index;
displayio_palette_get_color(self->palette, colorspace, &tmp_pixel, output_color);
if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) {
displayio_palette_get_color(self->pixel_shader, colorspace, &tmp_pixel, output_color);
} else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) {
displayio_colorconverter_convert(self->pixel_shader, colorspace, &tmp_pixel, output_color);
}

}

bool tilepalettemapper_tilepalettemapper_needs_refresh(tilepalettemapper_tilepalettemapper_t *self) {
Expand Down
4 changes: 2 additions & 2 deletions shared-module/tilepalettemapper/TilePaletteMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@

typedef struct {
mp_obj_base_t base;
mp_obj_t palette;
mp_obj_t pixel_shader;
uint16_t width_in_tiles;
uint16_t height_in_tiles;
uint16_t input_color_count;
uint16_t **tile_mappings;
uint32_t **tile_mappings;
bool needs_refresh;
} tilepalettemapper_tilepalettemapper_t;

Expand Down