Merge pull request #8 from Vogtinator/fbdev24
[WIP] Initial support for 24bit fbdev
This commit is contained in:
commit
c73ccd28f2
@ -55,6 +55,7 @@ struct fbdev_display {
|
||||
unsigned int stride;
|
||||
|
||||
bool xrgb32;
|
||||
bool rgb24;
|
||||
bool rgb16;
|
||||
unsigned int Bpp;
|
||||
unsigned int off_r;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user