uterm: video: add blitting support
authorDavid Herrmann <dh.herrmann@googlemail.com>
Sat, 23 Jun 2012 23:03:56 +0000 (01:03 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Sat, 23 Jun 2012 23:03:56 +0000 (01:03 +0200)
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>
src/uterm.h
src/uterm_video.c
src/uterm_video_fbdev.c

index c65689b..b33f0d4 100644 (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 */
 
index 5b74eee..463c14a 100644 (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;
index 52925dd..83fa50b 100644 (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 = {