summaryrefslogtreecommitdiff
path: root/shared-module/displayio/TileGrid.c
diff options
context:
space:
mode:
authorsommersoft <sommersoft@users.noreply.github.com>2019-07-27 10:46:53 -0500
committerGitHub <noreply@github.com>2019-07-27 10:46:53 -0500
commitcebdadd0f6122826337c962b3d443bd41d1de69d (patch)
treee2aeb661c3760f7aaf152bc1bbd95fd120161ab8 /shared-module/displayio/TileGrid.c
parentc335f170d7d561d07ca7412da60c260e13c5e746 (diff)
parentd99d3bd471920cdd9b2683b7dbd538551f7aee43 (diff)
Merge branch 'master' into dynamic_support_matrix
Diffstat (limited to 'shared-module/displayio/TileGrid.c')
-rw-r--r--shared-module/displayio/TileGrid.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c
index cdca45a29..88873d3a9 100644
--- a/shared-module/displayio/TileGrid.c
+++ b/shared-module/displayio/TileGrid.c
@@ -291,7 +291,7 @@ void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint
self->full_change = true;
}
-bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
+bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const _displayio_colorspace_t* colorspace, const displayio_area_t* area, uint32_t* mask, uint32_t *buffer) {
// If no tiles are present we have no impact.
uint8_t* tiles = self->tiles;
if (self->inline_tiles) {
@@ -371,14 +371,15 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_ar
y_shift = temp_shift;
}
+ uint8_t pixels_per_byte = 8 / colorspace->depth;
for (int16_t y = start_y; y < end_y; y++) {
- int16_t row_start = start + (y - start_y + y_shift) * y_stride;
+ int16_t row_start = start + (y - start_y + y_shift) * y_stride; // in pixels
int16_t local_y = y / self->absolute_transform->scale;
for (int16_t x = start_x; x < end_x; x++) {
// Compute the destination pixel in the buffer and mask based on the transformations.
- int16_t offset = row_start + (x - start_x + x_shift) * x_stride;
+ int16_t offset = row_start + (x - start_x + x_shift) * x_stride; // in pixels
- // This is super useful for debugging out range accesses. Uncomment to use.
+ // This is super useful for debugging out of range accesses. Uncomment to use.
// if (offset < 0 || offset >= (int32_t) displayio_area_size(area)) {
// asm("bkpt");
// }
@@ -404,23 +405,38 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const displayio_ar
value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, tile_x, tile_y);
}
- uint16_t* pixel = ((uint16_t*) buffer) + offset;
+ uint32_t pixel;
+ bool opaque = true;
if (self->pixel_shader == mp_const_none) {
- *pixel = value;
- return true;
+ pixel = value;
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_palette_type)) {
- if (!displayio_palette_get_color(self->pixel_shader, value, pixel)) {
- // A pixel is transparent so we haven't fully covered the area ourselves.
- full_coverage = false;
- } else {
- mask[offset / 32] |= 1 << (offset % 32);
- }
+ opaque = displayio_palette_get_color(self->pixel_shader, colorspace, value, &pixel);
} else if (MP_OBJ_IS_TYPE(self->pixel_shader, &displayio_colorconverter_type)) {
- if (!common_hal_displayio_colorconverter_convert(self->pixel_shader, value, pixel)) {
- // A pixel is transparent so we haven't fully covered the area ourselves.
- full_coverage = false;
- } else {
- mask[offset / 32] |= 1 << (offset % 32);
+ opaque = displayio_colorconverter_convert(self->pixel_shader, colorspace, value, &pixel);
+ }
+ if (!opaque) {
+ // A pixel is transparent so we haven't fully covered the area ourselves.
+ full_coverage = false;
+ } else {
+ mask[offset / 32] |= 1 << (offset % 32);
+ if (colorspace->depth == 16) {
+ *(((uint16_t*) buffer) + offset) = pixel;
+ } else if (colorspace->depth == 8) {
+ *(((uint8_t*) buffer) + offset) = pixel;
+ } else if (colorspace->depth < 8) {
+ // Reorder the offsets to pack multiple rows into a byte (meaning they share a column).
+ if (!colorspace->pixels_in_byte_share_row) {
+ uint16_t width = displayio_area_width(area);
+ uint16_t row = offset / width;
+ uint16_t col = offset % width;
+ // Dividing by pixels_per_byte does truncated division even if we multiply it back out.
+ offset = col * pixels_per_byte + (row / pixels_per_byte) * pixels_per_byte * width + row % pixels_per_byte;
+ // Also useful for validating that the bitpacking worked correctly.
+ // if (offset > displayio_area_size(area)) {
+ // asm("bkpt");
+ // }
+ }
+ ((uint8_t*)buffer)[offset / pixels_per_byte] |= pixel << ((offset % pixels_per_byte) * colorspace->depth);
}
}
}
@@ -449,7 +465,7 @@ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) {
displayio_area_t* displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *self, displayio_area_t* tail) {
if (self->moved && !self->first_draw) {
displayio_area_union(&self->previous_area, &self->current_area, &self->dirty_area);
- if (displayio_area_size(&self->dirty_area) <= 2 * self->pixel_width * self->pixel_height) {
+ if (displayio_area_size(&self->dirty_area) <= 2U * self->pixel_width * self->pixel_height) {
self->dirty_area.next = tail;
return &self->dirty_area;
}