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 <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-06-24 01:03:56 +02:00
parent eec3f2ad85
commit 749f653e66
3 changed files with 70 additions and 0 deletions

View File

@ -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 */

View File

@ -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;

View File

@ -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 = {