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:
parent
eec3f2ad85
commit
749f653e66
12
src/uterm.h
12
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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user