Merge pull request #8 from Vogtinator/fbdev24

[WIP] Initial support for 24bit fbdev
This commit is contained in:
Aetf 2018-09-05 15:47:19 -04:00 committed by GitHub
commit c73ccd28f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 6 deletions

View File

@ -55,6 +55,7 @@ struct fbdev_display {
unsigned int stride;
bool xrgb32;
bool rgb24;
bool rgb16;
unsigned int Bpp;
unsigned int off_r;

View File

@ -100,6 +100,21 @@ static uint_fast32_t xrgb32_to_device(struct uterm_display *disp,
return res;
}
static void write_24bit(uint8_t *dst, uint_fast32_t value)
{
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
dst[0] = value;
dst[1] = value >> 8;
dst[2] = value >> 16;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
dst[0] = value >> 16;
dst[1] = value >> 8;
dst[2] = value;
#else
#error "Unknown endianness"
#endif
}
int uterm_fbdev_display_blit(struct uterm_display *disp,
const struct uterm_video_buffer *buf,
unsigned int x, unsigned int y)
@ -151,6 +166,16 @@ int uterm_fbdev_display_blit(struct uterm_display *disp,
dst += fbdev->stride;
src += buf->stride;
}
} else if (fbdev->Bpp == 3) {
while (height--) {
for (i = 0; i < width; ++i) {
val = ((uint32_t*)src)[i];
uint_fast32_t full = xrgb32_to_device(disp, val);
write_24bit(&dst[i * 3], full);
}
dst += fbdev->stride;
src += buf->stride;
}
} else if (fbdev->Bpp == 4) {
while (height--) {
for (i = 0; i < width; ++i) {
@ -272,6 +297,35 @@ int uterm_fbdev_display_fake_blendv(struct uterm_display *disp,
dst += fbdev->stride;
src += req->buf->stride;
}
} else if (fbdev->Bpp == 3) {
while (height--) {
for (i = 0; i < width; ++i) {
if (src[i] == 0) {
r = req->br;
g = req->bg;
b = req->bb;
} else if (src[i] == 255) {
r = req->fr;
g = req->fg;
b = req->fb;
} else {
r = req->fr * src[i] +
req->br * (255 - src[i]);
r /= 256;
g = req->fg * src[i] +
req->bg * (255 - src[i]);
g /= 256;
b = req->fb * src[i] +
req->bb * (255 - src[i]);
b /= 256;
}
val = (r << 16) | (g << 8) | b;
uint_fast32_t full = xrgb32_to_device(disp, val);
write_24bit(&dst[i * 3], full);
}
dst += fbdev->stride;
src += req->buf->stride;
}
} else if (fbdev->Bpp == 4) {
while (height--) {
for (i = 0; i < width; ++i) {
@ -358,6 +412,13 @@ int uterm_fbdev_display_fill(struct uterm_display *disp,
dst += fbdev->stride;
}
}
} else if (fbdev->Bpp == 3) {
while (height--) {
for (i = 0; i < width * 3; i += 3) {
write_24bit(&dst[i], full_val);
}
dst += fbdev->stride;
}
} else if (fbdev->Bpp == 4) {
while (height--) {
for (i = 0; i < width; ++i)

View File

@ -132,9 +132,7 @@ static int display_activate_force(struct uterm_display *disp,
struct uterm_mode *mode,
bool force)
{
/* TODO: Add support for 24-bpp. However, we need to check how 3-bytes
* integers are assembled in big/little/mixed endian systems. */
static const char depths[] = { 32, 16, 0 };
static const char depths[] = { 32, 24, 16, 0 };
struct fbdev_display *dfb = disp->data;
struct uterm_mode *m;
struct fbdev_mode *mfb;
@ -217,14 +215,19 @@ static int display_activate_force(struct uterm_display *disp,
if (finfo->visual != FB_VISUAL_TRUECOLOR ||
vinfo->bits_per_pixel != 32) {
for (i = 0; depths[i]; ++i) {
vinfo->bits_per_pixel = depths[i];
vinfo->activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
/* Try to set a new mode and if it's successful... */
struct fb_var_screeninfo vinfo_new = *vinfo;
vinfo_new.bits_per_pixel = depths[i];
vinfo_new.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
ret = ioctl(dfb->fd, FBIOPUT_VSCREENINFO,
vinfo);
&vinfo_new);
if (ret < 0)
continue;
/* ... keep it. */
*vinfo = vinfo_new;
ret = refresh_info(disp);
if (ret)
goto err_close;
@ -235,6 +238,7 @@ static int display_activate_force(struct uterm_display *disp,
}
if (vinfo->bits_per_pixel != 32 &&
vinfo->bits_per_pixel != 24 &&
vinfo->bits_per_pixel != 16) {
log_error("device %s does not support 16/32 bpp but: %u",
dfb->node, vinfo->bits_per_pixel);
@ -333,6 +337,10 @@ static int display_activate_force(struct uterm_display *disp,
dfb->off_r == 11 && dfb->off_g == 5 && dfb->off_b == 0 &&
dfb->Bpp == 2)
dfb->rgb16 = true;
else 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 == 3)
dfb->rgb24 = true;
/* TODO: make dithering configurable */
disp->flags |= DISPLAY_DITHERING;
@ -455,6 +463,8 @@ static int display_get_buffers(struct uterm_display *disp,
f = UTERM_FORMAT_XRGB32;
else if (dfb->rgb16)
f = UTERM_FORMAT_RGB16;
else if (dfb->rgb24)
f = UTERM_FORMAT_RGB24;
if (!(formats & f))
return -EOPNOTSUPP;

View File

@ -100,6 +100,7 @@ enum uterm_video_format {
UTERM_FORMAT_GREY = 0x01,
UTERM_FORMAT_XRGB32 = 0x02,
UTERM_FORMAT_RGB16 = 0x04,
UTERM_FORMAT_RGB24 = 0x08,
};
struct uterm_video_buffer {