diff --git a/src/uterm_fbdev_internal.h b/src/uterm_fbdev_internal.h index b0ac72e..722d1f5 100644 --- a/src/uterm_fbdev_internal.h +++ b/src/uterm_fbdev_internal.h @@ -55,6 +55,7 @@ struct fbdev_display { unsigned int stride; bool xrgb32; + bool rgb16; unsigned int Bpp; unsigned int off_r; unsigned int off_g; diff --git a/src/uterm_fbdev_video.c b/src/uterm_fbdev_video.c index 2467cf8..b4cae9e 100644 --- a/src/uterm_fbdev_video.c +++ b/src/uterm_fbdev_video.c @@ -323,10 +323,15 @@ static int display_activate_force(struct uterm_display *disp, dfb->dither_g = 0; dfb->dither_b = 0; dfb->xrgb32 = false; + dfb->rgb16 = false; if (dfb->len_r == 8 && dfb->len_g == 8 && dfb->len_b == 8 && dfb->off_r == 16 && dfb->off_g == 8 && dfb->off_b == 0 && dfb->Bpp == 4) dfb->xrgb32 = true; + else if (dfb->len_r == 5 && dfb->len_g == 6 && dfb->len_b == 5 && + dfb->off_r == 11 && dfb->off_g == 5 && dfb->off_b == 0 && + dfb->Bpp == 2) + dfb->rgb16 = true; /* TODO: make dithering configurable */ disp->flags |= DISPLAY_DITHERING; @@ -425,6 +430,30 @@ static int display_set_dpms(struct uterm_display *disp, int state) return 0; } +static int display_get_buffer(struct uterm_display *disp, + struct uterm_video_buffer *buffer, + unsigned int formats) +{ + struct fbdev_display *dfb = disp->data; + unsigned int f = 0; + + if (dfb->xrgb32) + f = UTERM_FORMAT_XRGB32; + else if (dfb->rgb16) + f = UTERM_FORMAT_RGB16; + + if (!(formats & f)) + return -EOPNOTSUPP; + + buffer->width = dfb->xres; + buffer->height = dfb->yres; + buffer->stride = dfb->stride; + buffer->format = f; + buffer->data = dfb->map; + + return 0; +} + static int display_swap(struct uterm_display *disp, bool immediate) { struct fbdev_display *dfb = disp->data; @@ -466,6 +495,7 @@ static const struct display_ops fbdev_display_ops = { .deactivate = display_deactivate, .set_dpms = display_set_dpms, .use = NULL, + .get_buffer = display_get_buffer, .swap = display_swap, .blit = uterm_fbdev_display_blit, .fake_blendv = uterm_fbdev_display_fake_blendv, diff --git a/src/uterm_video.c b/src/uterm_video.c index 266de71..60455b6 100644 --- a/src/uterm_video.c +++ b/src/uterm_video.c @@ -423,6 +423,17 @@ int uterm_display_use(struct uterm_display *disp) return VIDEO_CALL(disp->ops->use, -EOPNOTSUPP, disp); } +int uterm_display_get_buffer(struct uterm_display *disp, + struct uterm_video_buffer *buffer, + unsigned int formats) +{ + if (!disp || !display_is_online(disp) || !buffer) + return -EINVAL; + + return VIDEO_CALL(disp->ops->get_buffer, -EOPNOTSUPP, disp, buffer, + formats); +} + int uterm_display_swap(struct uterm_display *disp, bool immediate) { if (!disp || !display_is_online(disp) || !video_is_awake(disp->video)) diff --git a/src/uterm_video.h b/src/uterm_video.h index 8d36c3d..2170b89 100644 --- a/src/uterm_video.h +++ b/src/uterm_video.h @@ -96,8 +96,9 @@ struct uterm_display_event { }; enum uterm_video_format { - UTERM_FORMAT_GREY, - UTERM_FORMAT_XRGB32, + UTERM_FORMAT_GREY = 0x01, + UTERM_FORMAT_XRGB32 = 0x02, + UTERM_FORMAT_RGB16 = 0x04, }; struct uterm_video_buffer { @@ -164,6 +165,9 @@ int uterm_display_set_dpms(struct uterm_display *disp, int state); int uterm_display_get_dpms(const struct uterm_display *disp); int uterm_display_use(struct uterm_display *disp); +int uterm_display_get_buffer(struct uterm_display *disp, + struct uterm_video_buffer *buffer, + unsigned int formats); int uterm_display_swap(struct uterm_display *disp, bool immediate); bool uterm_display_is_swapping(struct uterm_display *disp); diff --git a/src/uterm_video_drm.c b/src/uterm_video_drm.c index 8cb2e1d..e72e258 100644 --- a/src/uterm_video_drm.c +++ b/src/uterm_video_drm.c @@ -819,6 +819,7 @@ static const struct display_ops drm_display_ops = { .deactivate = display_deactivate, .set_dpms = uterm_drm_display_set_dpms, .use = display_use, + .get_buffer = NULL, .swap = display_swap, .blit = display_blit, .fake_blendv = display_fake_blendv, diff --git a/src/uterm_video_dumb.c b/src/uterm_video_dumb.c index dafe56b..130f5e3 100644 --- a/src/uterm_video_dumb.c +++ b/src/uterm_video_dumb.c @@ -240,6 +240,27 @@ static void display_deactivate(struct uterm_display *disp) disp->current_mode = NULL; } +static int display_get_buffer(struct uterm_display *disp, + struct uterm_video_buffer *buffer, + unsigned int formats) +{ + struct uterm_drm2d_display *d2d = uterm_drm_display_get_data(disp); + struct uterm_drm2d_rb *rb; + + if (!(formats & UTERM_FORMAT_XRGB32)) + return -EOPNOTSUPP; + + rb = &d2d->rb[d2d->current_rb ^ 1]; + + buffer->width = uterm_drm_mode_get_width(disp->current_mode); + buffer->height = uterm_drm_mode_get_height(disp->current_mode); + buffer->stride = rb->stride; + buffer->format = UTERM_FORMAT_XRGB32; + buffer->data = rb->map; + + return 0; +} + static int display_swap(struct uterm_display *disp, bool immediate) { int ret, rb; @@ -427,6 +448,7 @@ static const struct display_ops dumb_display_ops = { .deactivate = display_deactivate, .set_dpms = uterm_drm_display_set_dpms, .use = NULL, + .get_buffer = display_get_buffer, .swap = display_swap, .blit = display_blit, .fake_blendv = display_fake_blendv, diff --git a/src/uterm_video_internal.h b/src/uterm_video_internal.h index c86b704..18725be 100644 --- a/src/uterm_video_internal.h +++ b/src/uterm_video_internal.h @@ -54,6 +54,9 @@ struct display_ops { void (*deactivate) (struct uterm_display *disp); int (*set_dpms) (struct uterm_display *disp, int state); int (*use) (struct uterm_display *disp); + int (*get_buffer) (struct uterm_display *disp, + struct uterm_video_buffer *buffer, + unsigned int formats); int (*swap) (struct uterm_display *disp, bool immediate); int (*blit) (struct uterm_display *disp, const struct uterm_video_buffer *buf,