uterm: video: add blend() helper
When drawing single glyphs we often have the glyph as alpha-only buffer so we can draw it with any color we want. blit() requires a full image that can be copied, so the new blend() helper is introduced which takes a foreground and background color and blends in an image. Only plain-alpha buffers are currently supported. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
6ab01cbf6b
commit
51b70bef52
@ -194,6 +194,11 @@ int uterm_screen_swap(struct uterm_screen *screen);
|
||||
int uterm_screen_blit(struct uterm_screen *screen,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y);
|
||||
int uterm_screen_blend(struct uterm_screen *screen,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y,
|
||||
uint8_t fr, uint8_t fg, uint8_t fb,
|
||||
uint8_t br, uint8_t bg, uint8_t bb);
|
||||
int uterm_screen_fill(struct uterm_screen *screen,
|
||||
uint8_t r, uint8_t g, uint8_t b,
|
||||
unsigned int x, unsigned int y,
|
||||
|
@ -58,6 +58,11 @@ struct display_ops {
|
||||
int (*blit) (struct uterm_display *disp,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y);
|
||||
int (*blend) (struct uterm_display *disp,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y,
|
||||
uint8_t fr, uint8_t fg, uint8_t fb,
|
||||
uint8_t br, uint8_t bg, uint8_t bb);
|
||||
int (*fill) (struct uterm_display *disp,
|
||||
uint8_t r, uint8_t g, uint8_t b, unsigned int x,
|
||||
unsigned int y, unsigned int width, unsigned int height);
|
||||
|
@ -144,6 +144,19 @@ int uterm_screen_blit(struct uterm_screen *screen,
|
||||
buf, x, y);
|
||||
}
|
||||
|
||||
int uterm_screen_blend(struct uterm_screen *screen,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y,
|
||||
uint8_t fr, uint8_t fg, uint8_t fb,
|
||||
uint8_t br, uint8_t bg, uint8_t bb)
|
||||
{
|
||||
if (!screen)
|
||||
return -EINVAL;
|
||||
|
||||
return VIDEO_CALL(screen->disp->ops->blend, -EOPNOTSUPP, screen->disp,
|
||||
buf, x, y, fr, fg, fb, br, bg, bb);
|
||||
}
|
||||
|
||||
int uterm_screen_fill(struct uterm_screen *screen,
|
||||
uint8_t r, uint8_t g, uint8_t b,
|
||||
unsigned int x, unsigned int y,
|
||||
|
@ -413,6 +413,72 @@ static int display_blit(struct uterm_display *disp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int display_blend(struct uterm_display *disp,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y,
|
||||
uint8_t fr, uint8_t fg, uint8_t fb,
|
||||
uint8_t br, uint8_t bg, uint8_t bb)
|
||||
{
|
||||
unsigned int tmp;
|
||||
uint8_t *dst, *src;
|
||||
struct dumb_rb *rb;
|
||||
unsigned int width, height, i;
|
||||
unsigned int sw, sh;
|
||||
unsigned int r, g, b;
|
||||
|
||||
if (!disp->video || !display_is_online(disp))
|
||||
return -EINVAL;
|
||||
if (!buf || !video_is_awake(disp->video))
|
||||
return -EINVAL;
|
||||
|
||||
rb = &disp->dumb.rb[disp->dumb.current_rb ^ 1];
|
||||
sw = disp->current_mode->dumb.info.hdisplay;
|
||||
sh = disp->current_mode->dumb.info.vdisplay;
|
||||
|
||||
tmp = x + buf->width;
|
||||
if (tmp < x || x >= sw)
|
||||
return -EINVAL;
|
||||
if (tmp > sw)
|
||||
width = sw - x;
|
||||
else
|
||||
width = buf->width;
|
||||
|
||||
tmp = y + buf->height;
|
||||
if (tmp < y || y >= sh)
|
||||
return -EINVAL;
|
||||
if (tmp > sh)
|
||||
height = sh - y;
|
||||
else
|
||||
height = buf->height;
|
||||
|
||||
dst = rb->map;
|
||||
dst = &dst[y * rb->stride + x * 4];
|
||||
src = buf->data;
|
||||
|
||||
if (buf->format == UTERM_FORMAT_GREY) {
|
||||
while (height--) {
|
||||
for (i = 0; i < width; ++i) {
|
||||
r = (fr & 0xff) * src[i] / 255 +
|
||||
(br & 0xff) * (255 - src[i]) / 255;
|
||||
g = (fg & 0xff) * src[i] / 255 +
|
||||
(bg & 0xff) * (255 - src[i]) / 255;
|
||||
b = (fb & 0xff) * src[i] / 255 +
|
||||
(bb & 0xff) * (255 - src[i]) / 255;
|
||||
((uint32_t*)dst)[i] =
|
||||
((r & 0xff) << 16) |
|
||||
((g & 0xff) << 8) |
|
||||
(b & 0xff);
|
||||
}
|
||||
dst += rb->stride;
|
||||
src += buf->stride;
|
||||
}
|
||||
} else {
|
||||
log_warning("using unsupported buffer format for blending");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int display_fill(struct uterm_display *disp,
|
||||
uint8_t r, uint8_t g, uint8_t b,
|
||||
unsigned int x, unsigned int y,
|
||||
@ -774,6 +840,7 @@ const struct display_ops dumb_display_ops = {
|
||||
.use = NULL,
|
||||
.swap = display_swap,
|
||||
.blit = display_blit,
|
||||
.blend = display_blend,
|
||||
.fill = display_fill,
|
||||
};
|
||||
|
||||
|
@ -380,6 +380,69 @@ static int display_blit(struct uterm_display *disp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int display_blend(struct uterm_display *disp,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y,
|
||||
uint8_t fr, uint8_t fg, uint8_t fb,
|
||||
uint8_t br, uint8_t bg, uint8_t bb)
|
||||
{
|
||||
unsigned int tmp;
|
||||
uint8_t *dst, *src;
|
||||
unsigned int width, height, i;
|
||||
unsigned int r, g, b;
|
||||
|
||||
if (!disp->video || !(disp->flags & DISPLAY_ONLINE))
|
||||
return -EINVAL;
|
||||
if (!buf || !video_is_awake(disp->video))
|
||||
return -EINVAL;
|
||||
|
||||
tmp = x + buf->width;
|
||||
if (tmp < x || x >= disp->fbdev.xres)
|
||||
return -EINVAL;
|
||||
if (tmp > disp->fbdev.xres)
|
||||
width = disp->fbdev.xres - x;
|
||||
else
|
||||
width = buf->width;
|
||||
|
||||
tmp = y + buf->height;
|
||||
if (tmp < y || y >= disp->fbdev.yres)
|
||||
return -EINVAL;
|
||||
if (tmp > disp->fbdev.yres)
|
||||
height = disp->fbdev.yres - y;
|
||||
else
|
||||
height = buf->height;
|
||||
|
||||
if (!(disp->flags & DISPLAY_DBUF) || disp->fbdev.bufid)
|
||||
dst = disp->fbdev.map;
|
||||
else
|
||||
dst = &disp->fbdev.map[disp->fbdev.yres * disp->fbdev.stride];
|
||||
dst = &dst[y * disp->fbdev.stride + x * disp->fbdev.bpp];
|
||||
src = buf->data;
|
||||
|
||||
if (buf->format == UTERM_FORMAT_GREY) {
|
||||
while (height--) {
|
||||
for (i = 0; i < width; ++i) {
|
||||
r = (fr & 0xff) * src[i] / 255 +
|
||||
(br & 0xff) * (255 - src[i]) / 255;
|
||||
g = (fg & 0xff) * src[i] / 255 +
|
||||
(bg & 0xff) * (255 - src[i]) / 255;
|
||||
b = (fb & 0xff) * src[i] / 255 +
|
||||
(bb & 0xff) * (255 - src[i]) / 255;
|
||||
((uint32_t*)dst)[i] =
|
||||
((r & 0xff) << 16) |
|
||||
((g & 0xff) << 8) |
|
||||
(b & 0xff);
|
||||
}
|
||||
dst += disp->fbdev.stride;
|
||||
src += buf->stride;
|
||||
}
|
||||
} else {
|
||||
log_warning("using unsupported buffer format for blending");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int display_fill(struct uterm_display *disp,
|
||||
uint8_t r, uint8_t g, uint8_t b,
|
||||
unsigned int x, unsigned int y,
|
||||
@ -516,6 +579,7 @@ const struct display_ops fbdev_display_ops = {
|
||||
.use = NULL,
|
||||
.swap = display_swap,
|
||||
.blit = display_blit,
|
||||
.blend = display_blend,
|
||||
.fill = display_fill,
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user