aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/vt/hw/fb/vt_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/vt/hw/fb/vt_fb.c')
-rw-r--r--sys/dev/vt/hw/fb/vt_fb.c84
1 files changed, 69 insertions, 15 deletions
diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c
index c1eeb5e69e08..6130dc4061b4 100644
--- a/sys/dev/vt/hw/fb/vt_fb.c
+++ b/sys/dev/vt/hw/fb/vt_fb.c
@@ -34,6 +34,7 @@
#include <sys/queue.h>
#include <sys/fbio.h>
#include <sys/kernel.h>
+#include <sys/endian.h>
#include <dev/vt/vt.h>
#include <dev/vt/hw/fb/vt_fb.h>
#include <dev/vt/colors/vt_termcolors.h>
@@ -49,6 +50,7 @@ static struct vt_driver vt_fb_driver = {
.vd_bitblt_text = vt_fb_bitblt_text,
.vd_invalidate_text = vt_fb_invalidate_text,
.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
+ .vd_bitblt_argb = vt_fb_bitblt_argb,
.vd_drawrect = vt_fb_drawrect,
.vd_setpixel = vt_fb_setpixel,
.vd_postswitch = vt_fb_postswitch,
@@ -73,15 +75,31 @@ static void
vt_fb_mem_wr2(struct fb_info *sc, uint32_t o, uint16_t v)
{
- KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
+ KASSERT((o + 1 < sc->fb_size), ("Offset %#08x out of fb size", o + 1));
*(uint16_t *)(sc->fb_vbase + o) = v;
}
static void
+vt_fb_mem_wr3(struct fb_info *sc, uint32_t o, uint32_t v)
+{
+ uint8_t *b = (uint8_t *)sc->fb_vbase + o;
+
+ KASSERT((o + 2 < sc->fb_size), ("Offset %#08x out of fb size", o + 2));
+ /*
+ * We want to write three bytes, independent
+ * of endianness. Multiply _QUAD_LOWWORD and
+ * _QUAD_HIGHWORD by 2 to skip the middle byte.
+ */
+ b[_QUAD_LOWWORD * 2] = v & 0xff;
+ b[1] = (v >> 8) & 0xff;
+ b[_QUAD_HIGHWORD * 2] = (v >> 16) & 0xff;
+}
+
+static void
vt_fb_mem_wr4(struct fb_info *sc, uint32_t o, uint32_t v)
{
- KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
+ KASSERT((o + 3 < sc->fb_size), ("Offset %#08x out of fb size", o + 3));
*(uint32_t *)(sc->fb_vbase + o) = v;
}
@@ -186,9 +204,7 @@ vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color)
vt_fb_mem_wr2(info, o, c);
break;
case 3:
- vt_fb_mem_wr1(info, o, (c >> 16) & 0xff);
- vt_fb_mem_wr1(info, o + 1, (c >> 8) & 0xff);
- vt_fb_mem_wr1(info, o + 2, c & 0xff);
+ vt_fb_mem_wr3(info, o, c);
break;
case 4:
vt_fb_mem_wr4(info, o, c);
@@ -245,12 +261,7 @@ vt_fb_blank(struct vt_device *vd, term_color_t color)
case 3:
for (h = 0; h < info->fb_height; h++)
for (o = 0; o < info->fb_stride - 2; o += 3) {
- vt_fb_mem_wr1(info, h*info->fb_stride + o,
- (c >> 16) & 0xff);
- vt_fb_mem_wr1(info, h*info->fb_stride + o + 1,
- (c >> 8) & 0xff);
- vt_fb_mem_wr1(info, h*info->fb_stride + o + 2,
- c & 0xff);
+ vt_fb_mem_wr3(info, h*info->fb_stride + o, c);
}
break;
case 4:
@@ -316,10 +327,7 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
vt_fb_mem_wr2(info, o, cc);
break;
case 3:
- /* Packed mode, so unaligned. Byte access. */
- vt_fb_mem_wr1(info, o, (cc >> 16) & 0xff);
- vt_fb_mem_wr1(info, o + 1, (cc >> 8) & 0xff);
- vt_fb_mem_wr1(info, o + 2, cc & 0xff);
+ vt_fb_mem_wr3(info, o, cc);
break;
case 4:
vt_fb_mem_wr4(info, o, cc);
@@ -332,6 +340,52 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
}
}
+int
+vt_fb_bitblt_argb(struct vt_device *vd, const struct vt_window *vw,
+ const uint8_t *argb,
+ unsigned int width, unsigned int height,
+ unsigned int x, unsigned int y)
+{
+ struct fb_info *info;
+ uint32_t o, cc;
+ int bpp, xi, yi;
+
+ info = vd->vd_softc;
+ bpp = FBTYPE_GET_BYTESPP(info);
+ if (bpp != 4)
+ return (EOPNOTSUPP);
+
+ if (info->fb_flags & FB_FLAG_NOWRITE)
+ return (0);
+
+ KASSERT((info->fb_vbase != 0), ("Unmapped framebuffer"));
+
+ /* Bound by right and bottom edges. */
+ if (y + height > vw->vw_draw_area.tr_end.tp_row) {
+ if (y >= vw->vw_draw_area.tr_end.tp_row)
+ return (EINVAL);
+ height = vw->vw_draw_area.tr_end.tp_row - y;
+ }
+ if (x + width > vw->vw_draw_area.tr_end.tp_col) {
+ if (x >= vw->vw_draw_area.tr_end.tp_col)
+ return (EINVAL);
+ width = vw->vw_draw_area.tr_end.tp_col - x;
+ }
+ for (yi = 0; yi < height; yi++) {
+ for (xi = 0; xi < (width * 4); xi += 4) {
+ o = (y + yi) * info->fb_stride + (x + (xi / 4)) * bpp;
+ o += vd->vd_transpose;
+ cc = (argb[yi * width * 4 + xi] << 16) |
+ (argb[yi * width * 4 + xi + 1] << 8) |
+ (argb[yi * width * 4 + xi + 2]) |
+ (argb[yi * width * 4 + xi + 3] << 24);
+ vt_fb_mem_wr4(info, o, cc);
+ }
+ }
+
+ return (0);
+}
+
void
vt_fb_bitblt_text(struct vt_device *vd, const struct vt_window *vw,
const term_rect_t *area)