From 749f653e66242b322d131fc68e76600642d0c40c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 24 Jun 2012 01:03:56 +0200 Subject: [PATCH] uterm: video: add blitting support All backends that do not provide OpenGL contexts can not implement buffer blitting so we can at least draw rectangular areas to the framebuffer. Signed-off-by: David Herrmann --- src/uterm.h | 12 +++++++++++ src/uterm_video.c | 12 +++++++++++ src/uterm_video_fbdev.c | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/src/uterm.h b/src/uterm.h index c65689b..b33f0d4 100644 --- a/src/uterm.h +++ b/src/uterm.h @@ -157,6 +157,14 @@ struct uterm_video_hotplug { int action; }; +struct uterm_video_buffer { + uint8_t *data; + unsigned int width; + unsigned int height; + unsigned int stride; + unsigned int bpp; +}; + typedef void (*uterm_video_cb) (struct uterm_video *video, struct uterm_video_hotplug *arg, void *data); @@ -177,6 +185,10 @@ unsigned int uterm_screen_height(struct uterm_screen *screen); int uterm_screen_use(struct uterm_screen *screen); 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, + unsigned int width, unsigned int height); /* display modes interface */ diff --git a/src/uterm_video.c b/src/uterm_video.c index 5b74eee..463c14a 100644 --- a/src/uterm_video.c +++ b/src/uterm_video.c @@ -134,6 +134,18 @@ int uterm_screen_swap(struct uterm_screen *screen) return VIDEO_CALL(screen->disp->ops->swap, 0, screen->disp); } +int uterm_screen_blit(struct uterm_screen *screen, + const struct uterm_video_buffer *buf, + unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + if (!screen) + return -EINVAL; + + return VIDEO_CALL(screen->disp->ops->blit, -EOPNOTSUPP, screen->disp, + buf, x, y, width, height); +} + int mode_new(struct uterm_mode **out, const struct mode_ops *ops) { struct uterm_mode *mode; diff --git a/src/uterm_video_fbdev.c b/src/uterm_video_fbdev.c index 52925dd..83fa50b 100644 --- a/src/uterm_video_fbdev.c +++ b/src/uterm_video_fbdev.c @@ -319,6 +319,51 @@ static int display_swap(struct uterm_display *disp) return 0; } +static int display_blit(struct uterm_display *disp, + const struct uterm_video_buffer *buf, + unsigned int x, unsigned int y, + unsigned int width, unsigned int height) +{ + unsigned int tmp; + uint8_t *dst, *src; + + log_debug("blit start"); + if (!disp->video || !(disp->flags & DISPLAY_ONLINE)) + return -EINVAL; + if (!buf || !video_is_awake(disp->video)) + return -EINVAL; + if (buf->bpp != disp->fbdev.bpp) + return -EINVAL; + + tmp = x + width; + if (tmp < x || x >= buf->width) + return -EINVAL; + if (tmp > buf->width) + width = buf->width - x; + tmp = y + height; + if (tmp < y || y >= buf->height) + return -EINVAL; + if (tmp > buf->height) + height = buf->height - y; + + if (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[y * buf->stride + x * buf->bpp]; + + log_debug("blitting %u %u %u %u %u %u", buf->width, buf->height, + x, y, width, height); + while (--height) { + memcpy(dst, src, buf->bpp * width); + dst += disp->fbdev.stride; + src += buf->stride; + } + + return 0; +} + static int video_init(struct uterm_video *video, const char *node) { int ret; @@ -405,6 +450,7 @@ const struct display_ops fbdev_display_ops = { .set_dpms = display_set_dpms, .use = NULL, .swap = display_swap, + .blit = display_blit, }; const struct video_ops fbdev_video_ops = {