fb: cfb: support inverting with coordinates that do not align with the tile

Improve `cfb_invert_area()` able to invert even at a coordinate
not on tile boundaries.

Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@fujitsu.com>
This commit is contained in:
TOKITA Hiroshi 2023-01-12 22:26:34 +09:00 committed by Carles Cufí
parent 5634691d8c
commit 7068587505

View file

@ -229,6 +229,7 @@ int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y,
uint16_t width, uint16_t height) uint16_t width, uint16_t height)
{ {
const struct char_framebuffer *fb = &char_fb; const struct char_framebuffer *fb = &char_fb;
const bool need_reverse = ((fb->screen_info & SCREEN_INFO_MONO_MSB_FIRST) != 0);
if (x >= fb->x_res || y >= fb->y_res) { if (x >= fb->x_res || y >= fb->y_res) {
LOG_ERR("Coordinates outside of framebuffer"); LOG_ERR("Coordinates outside of framebuffer");
@ -236,7 +237,15 @@ int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y,
return -EINVAL; return -EINVAL;
} }
if ((fb->screen_info & SCREEN_INFO_MONO_VTILED) && !(y % 8)) { if ((fb->screen_info & SCREEN_INFO_MONO_VTILED)) {
if (x > fb->x_res) {
x = fb->x_res;
}
if (y > fb->y_res) {
y = fb->y_res;
}
if (x + width > fb->x_res) { if (x + width > fb->x_res) {
width = fb->x_res - x; width = fb->x_res - x;
} }
@ -246,10 +255,46 @@ int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y,
} }
for (size_t i = x; i < x + width; i++) { for (size_t i = x; i < x + width; i++) {
for (size_t j = y / 8U; j < (y + height) / 8U; j++) { for (size_t j = y; j < (y + height); j++) {
size_t index = (j * fb->x_res) + i; /*
* Process inversion in the y direction
* by separating per 8-line boundaries.
*/
fb->buf[index] = ~fb->buf[index]; const size_t index = ((j / 8) * fb->x_res) + i;
const uint8_t remains = y + height - j;
/*
* Make mask to prevent overwriting the drawing contents that on
* between the start line or end line and the 8-line boundary.
*/
if ((j % 8) > 0) {
uint8_t m = BIT_MASK((j % 8));
uint8_t b = fb->buf[index];
if (need_reverse) {
m = byte_reverse(m);
b = byte_reverse(b);
}
fb->buf[index] = ~(b | m) | (b & m);
j += 7 - (j % 8);
} else if (remains >= 8) {
/* No mask required if no start or end line is included */
fb->buf[index] = ~fb->buf[index];
j += 7;
} else {
uint8_t m = BIT_MASK(remains % 8) << (8 - (remains % 8));
uint8_t b = fb->buf[index];
if (need_reverse) {
m = byte_reverse(m);
b = byte_reverse(b);
}
fb->buf[index] = ~(b | m) | (b & m);
j += (remains - 1);
}
} }
} }