summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/sys/boot/common/gfx_fb.c1210
-rw-r--r--usr/src/boot/sys/boot/common/gfx_fb.h16
-rw-r--r--usr/src/boot/sys/boot/common/tem.c126
-rw-r--r--usr/src/boot/sys/boot/efi/libefi/efi_console.c8
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/vbe.c2
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/vbe.h2
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/vidconsole.c38
-rw-r--r--usr/src/boot/sys/sys/tem_impl.h4
-rw-r--r--usr/src/common/font/font.c21
-rw-r--r--usr/src/uts/common/sys/rgb.h35
10 files changed, 812 insertions, 650 deletions
diff --git a/usr/src/boot/sys/boot/common/gfx_fb.c b/usr/src/boot/sys/boot/common/gfx_fb.c
index 361076fc2b..6331a28ab7 100644
--- a/usr/src/boot/sys/boot/common/gfx_fb.c
+++ b/usr/src/boot/sys/boot/common/gfx_fb.c
@@ -16,13 +16,64 @@
*/
/*
- * Common functions to implement graphical framebuffer support for console.
+ * The workhorse here is gfxfb_blt(). It is implemented to mimic UEFI
+ * GOP Blt, and allows us to fill the rectangle on screen, copy
+ * rectangle from video to buffer and buffer to video and video to video.
+ * Such implementation does allow us to have almost identical implementation
+ * for both BIOS VBE and UEFI.
+ *
+ * ALL pixel data is assumed to be 32-bit BGRA (byte order Blue, Green, Red,
+ * Alpha) format, this allows us to only handle RGB data and not to worry
+ * about mixing RGB with indexed colors.
+ * Data exchange between memory buffer and video will translate BGRA
+ * and native format as following:
+ *
+ * 32-bit to/from 32-bit is trivial case.
+ * 32-bit to/from 24-bit is also simple - we just drop the alpha channel.
+ * 32-bit to/from 16-bit is more complicated, because we nee to handle
+ * data loss from 32-bit to 16-bit. While reading/writing from/to video, we
+ * need to apply masks of 16-bit color components. This will preserve
+ * colors for terminal text. For 32-bit truecolor PMG images, we need to
+ * translate 32-bit colors to 15/16 bit colors and this means data loss.
+ * There are different algorithms how to perform such color space reduction,
+ * we are currently using bitwise right shift to reduce color space and so far
+ * this technique seems to be sufficient (see also gfx_fb_putimage(), the
+ * end of for loop).
+ * 32-bit to/from 8-bit is the most troublesome because 8-bit colors are
+ * indexed. From video, we do get color indexes, and we do translate
+ * color index values to RGB. To write to video, we again need to translate
+ * RGB to color index. Additionally, we need to translate between VGA and
+ * Sun colors.
+ *
+ * Our internal color data is represented using BGRA format. But the hardware
+ * used indexed colors for 8-bit colors (0-255) and for this mode we do
+ * need to perform translation to/from BGRA and index values.
+ *
+ * - paletteentry RGB <-> index -
+ * BGRA BUFFER <----/ \ - VIDEO
+ * \ /
+ * - RGB (16/24/32) -
+ *
+ * To perform index to RGB translation, we use palette table generated
+ * from when we set up 8-bit mode video. We cannot read palette data from
+ * the hardware, because not all hardware supports reading it.
+ *
+ * BGRA to index is implemented in rgb_to_color_index() by searching
+ * palette array for closest match of RBG values.
+ *
+ * Note: In 8-bit mode, We do store first 16 colors to palette registers
+ * in VGA color order, this serves two purposes; firstly,
+ * if palette update is not supported, we still have correct 16 colors.
+ * Secondly, the kernel does get correct 16 colors when some other boot
+ * loader is used. However, the palette map for 8-bit colors is using
+ * Sun color ordering - this does allow us to skip translation
+ * from VGA colors to Sun colors, while we are reading RGB data.
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <stand.h>
-#if defined(EFI)
+#if defined(EFI)
#include <efi.h>
#include <efilib.h>
#else
@@ -59,25 +110,16 @@ static int gfx_inverse = 0;
static int gfx_inverse_screen = 0;
static uint8_t gfx_fg = DEFAULT_ANSI_FOREGROUND;
static uint8_t gfx_bg = DEFAULT_ANSI_BACKGROUND;
-#if defined(EFI)
+#if defined(EFI)
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GlyphBuffer;
-static size_t GlyphBufferSize;
+#else
+static struct paletteentry *GlyphBuffer;
#endif
+static size_t GlyphBufferSize;
-static int gfx_fb_cons_clear(struct vis_consclear *);
-static void gfx_fb_cons_copy(struct vis_conscopy *);
-static void gfx_fb_cons_display(struct vis_consdisplay *);
-
-#if defined(EFI)
-static int gfx_gop_cons_clear(uint32_t data, uint32_t width, uint32_t height);
-static void gfx_gop_cons_copy(struct vis_conscopy *);
-static void gfx_gop_cons_display(struct vis_consdisplay *);
-static void gfx_gop_display_cursor(struct vis_conscursor *);
-#endif
-static int gfx_bm_cons_clear(uint32_t data, uint32_t width, uint32_t height);
-static void gfx_bm_cons_copy(struct vis_conscopy *);
-static void gfx_bm_cons_display(struct vis_consdisplay *);
-static void gfx_bm_display_cursor(struct vis_conscursor *);
+int gfx_fb_cons_clear(struct vis_consclear *);
+void gfx_fb_cons_copy(struct vis_conscopy *);
+void gfx_fb_cons_display(struct vis_consdisplay *);
static bool insert_font(char *, FONT_FLAGS);
@@ -90,17 +132,6 @@ static bool insert_font(char *, FONT_FLAGS);
* Task Priority Level (TPL) to TPL_NOTIFY, which is highest priority
* usable in application.
*/
-struct gfx_fb_ops {
- int (*gfx_cons_clear)(uint32_t, uint32_t, uint32_t);
- void (*gfx_cons_copy)(struct vis_conscopy *);
- void (*gfx_cons_display)(struct vis_consdisplay *);
- void (*gfx_cons_display_cursor)(struct vis_conscursor *);
-} gfx_fb_ops = {
- .gfx_cons_clear = gfx_bm_cons_clear,
- .gfx_cons_copy = gfx_bm_cons_copy,
- .gfx_cons_display = gfx_bm_cons_display,
- .gfx_cons_display_cursor = gfx_bm_display_cursor
-};
/*
* Translate platform specific FB address.
@@ -108,7 +139,7 @@ struct gfx_fb_ops {
static uint8_t *
gfx_get_fb_address(void)
{
-#if defined(EFI)
+#if defined(EFI)
return ((uint8_t *)(uintptr_t)
gfx_fb.framebuffer_common.framebuffer_addr);
#else
@@ -174,28 +205,35 @@ gfx_parse_mode_str(char *str, int *x, int *y, int *depth)
/*
* Support for color mapping.
+ * For 8, 24 and 32 bit depth, use mask size 8.
+ * 15/16 bit depth needs to use mask size from mode,
+ * or we will lose color information from 32-bit to 15/16 bit translation.
*/
uint32_t
gfx_fb_color_map(uint8_t index)
{
rgb_t rgb;
+ int bpp;
- if (gfx_fb.framebuffer_common.framebuffer_type !=
- MULTIBOOT_FRAMEBUFFER_TYPE_RGB) {
- if (index < nitems(solaris_color_to_pc_color))
- return (solaris_color_to_pc_color[index]);
- else
- return (index);
- }
+ bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
- rgb.red.pos = gfx_fb.u.fb2.framebuffer_red_field_position;
- rgb.red.size = gfx_fb.u.fb2.framebuffer_red_mask_size;
+ rgb.red.pos = 16;
+ if (bpp == 2)
+ rgb.red.size = gfx_fb.u.fb2.framebuffer_red_mask_size;
+ else
+ rgb.red.size = 8;
- rgb.green.pos = gfx_fb.u.fb2.framebuffer_green_field_position;
- rgb.green.size = gfx_fb.u.fb2.framebuffer_green_mask_size;
+ rgb.green.pos = 8;
+ if (bpp == 2)
+ rgb.green.size = gfx_fb.u.fb2.framebuffer_green_mask_size;
+ else
+ rgb.green.size = 8;
- rgb.blue.pos = gfx_fb.u.fb2.framebuffer_blue_field_position;
- rgb.blue.size = gfx_fb.u.fb2.framebuffer_blue_mask_size;
+ rgb.blue.pos = 0;
+ if (bpp == 2)
+ rgb.blue.size = gfx_fb.u.fb2.framebuffer_blue_mask_size;
+ else
+ rgb.blue.size = 8;
return (rgb_color_map(&rgb, index));
}
@@ -328,31 +366,16 @@ gfx_set_inverses(struct env_var *ev, int flags, const void *value)
* Initialize gfx framework.
*/
void
-gfx_framework_init(struct visual_ops *fb_ops)
+gfx_framework_init(void)
{
int rc, limit;
char *env, buf[2];
-#if defined(EFI)
- extern EFI_GRAPHICS_OUTPUT *gop;
-
- if (gop != NULL) {
- gfx_fb_ops.gfx_cons_clear = gfx_gop_cons_clear;
- gfx_fb_ops.gfx_cons_copy = gfx_gop_cons_copy;
- gfx_fb_ops.gfx_cons_display = gfx_gop_cons_display;
- gfx_fb_ops.gfx_cons_display_cursor = gfx_gop_display_cursor;
- }
-#endif
if (gfx_fb.framebuffer_common.framebuffer_bpp < 24)
limit = 7;
else
limit = 255;
- /* Add visual io callbacks */
- fb_ops->cons_clear = gfx_fb_cons_clear;
- fb_ops->cons_copy = gfx_fb_cons_copy;
- fb_ops->cons_display = gfx_fb_cons_display;
-
/* set up tem inverse controls */
env = getenv("tem.inverse");
if (env != NULL) {
@@ -415,159 +438,562 @@ gfx_framework_init(struct visual_ops *fb_ops)
}
/*
- * visual io callbacks.
+ * Get indexed color from RGB. This function is used to write data to video
+ * memory when the adapter is set to use indexed colors.
+ * Since UEFI does only support 32-bit colors, we do not implement it for
+ * UEFI because there is no need for it and we do not have palette array
+ * for UEFI.
*/
+static uint8_t
+rgb_to_color_index(uint8_t r, uint8_t g, uint8_t b)
+{
+#if !defined(EFI)
+ uint32_t color, best, dist, k;
+ int diff;
+
+ color = 0;
+ best = 255 * 255 * 255;
+ for (k = 0; k < NCMAP; k++) {
+ diff = r - pe8[k].Red;
+ dist = diff * diff;
+ diff = g - pe8[k].Green;
+ dist += diff * diff;
+ diff = b - pe8[k].Blue;
+ dist += diff * diff;
+
+ /* Exact match, exit the loop */
+ if (dist == 0)
+ break;
-#if defined(EFI)
-static int
-gfx_gop_cons_clear(uint32_t data, uint32_t width, uint32_t height)
+ if (dist < best) {
+ color = k;
+ best = dist;
+ }
+ }
+ if (k == NCMAP)
+ k = color;
+ return (k);
+#else
+ (void) r;
+ (void) g;
+ (void) b;
+ return (0);
+#endif
+}
+
+static void
+gfx_mem_wr1(uint8_t *base, size_t size, uint32_t o, uint8_t v)
{
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
- EFI_STATUS status;
- extern EFI_GRAPHICS_OUTPUT *gop;
- BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)&data;
+ if (o >= size)
+ return;
+ *(uint8_t *)(base + o) = v;
+}
- status = gop->Blt(gop, BltBuffer, EfiBltVideoFill, 0, 0,
- 0, 0, width, height, 0);
+static void
+gfx_mem_wr2(uint8_t *base, size_t size, uint32_t o, uint16_t v)
+{
- if (EFI_ERROR(status))
- return (1);
- else
- return (0);
+ if (o >= size)
+ return;
+ *(uint16_t *)(base + o) = v;
+}
+
+static void
+gfx_mem_wr4(uint8_t *base, size_t size, uint32_t o, uint32_t v)
+{
+
+ if (o >= size)
+ return;
+ *(uint32_t *)(base + o) = v;
}
-#endif
static int
-gfx_bm_cons_clear(uint32_t data, uint32_t width, uint32_t height)
+gfxfb_blt_fill(void *BltBuffer,
+ uint32_t DestinationX, uint32_t DestinationY,
+ uint32_t Width, uint32_t Height)
{
- uint8_t *fb, *fb8;
- uint32_t *fb32, pitch;
- uint16_t *fb16;
- uint32_t i, j;
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p;
+#else
+ struct paletteentry *p;
+#endif
+ uint32_t data, bpp, pitch, y, x;
+ size_t size;
+ off_t off;
+ uint8_t *destination;
- fb = gfx_get_fb_address();
- pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
+ if (BltBuffer == NULL)
+ return (EINVAL);
- switch (gfx_fb.framebuffer_common.framebuffer_bpp) {
- case 8: /* 8 bit */
- for (i = 0; i < height; i++) {
- (void) memset(fb + i * pitch, data, pitch);
- }
- break;
- case 15:
- case 16: /* 16 bit */
- for (i = 0; i < height; i++) {
- fb16 = (uint16_t *)(fb + i * pitch);
- for (j = 0; j < width; j++)
- fb16[j] = (uint16_t)(data & 0xffff);
- }
- break;
- case 24: /* 24 bit */
- for (i = 0; i < height; i++) {
- fb8 = fb + i * pitch;
- for (j = 0; j < pitch; j += 3) {
- fb8[j] = (data >> 16) & 0xff;
- fb8[j+1] = (data >> 8) & 0xff;
- fb8[j+2] = data & 0xff;
+ if (DestinationY + Height >
+ gfx_fb.framebuffer_common.framebuffer_height)
+ return (EINVAL);
+
+ if (DestinationX + Width > gfx_fb.framebuffer_common.framebuffer_width)
+ return (EINVAL);
+
+ if (Width == 0 || Height == 0)
+ return (EINVAL);
+
+ p = BltBuffer;
+ if (gfx_fb.framebuffer_common.framebuffer_bpp == 8) {
+ data = rgb_to_color_index(p->Red, p->Green, p->Blue);
+ } else {
+ data = (p->Red &
+ ((1 << gfx_fb.u.fb2.framebuffer_red_mask_size) - 1)) <<
+ gfx_fb.u.fb2.framebuffer_red_field_position;
+ data |= (p->Green &
+ ((1 << gfx_fb.u.fb2.framebuffer_green_mask_size) - 1)) <<
+ gfx_fb.u.fb2.framebuffer_green_field_position;
+ data |= (p->Blue &
+ ((1 << gfx_fb.u.fb2.framebuffer_blue_mask_size) - 1)) <<
+ gfx_fb.u.fb2.framebuffer_blue_field_position;
+ }
+
+ bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
+ pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
+ destination = gfx_get_fb_address();
+ size = gfx_fb.framebuffer_common.framebuffer_height * pitch;
+
+ for (y = DestinationY; y < Height + DestinationY; y++) {
+ off = y * pitch + DestinationX * bpp;
+ for (x = 0; x < Width; x++) {
+ switch (bpp) {
+ case 1:
+ gfx_mem_wr1(destination, size, off,
+ (data < NCOLORS) ?
+ solaris_color_to_pc_color[data] : data);
+ break;
+ case 2:
+ gfx_mem_wr2(destination, size, off, data);
+ break;
+ case 3:
+ gfx_mem_wr1(destination, size, off,
+ (data >> 16) & 0xff);
+ gfx_mem_wr1(destination, size, off + 1,
+ (data >> 8) & 0xff);
+ gfx_mem_wr1(destination, size, off + 2,
+ data & 0xff);
+ break;
+ case 4:
+ gfx_mem_wr4(destination, size, off, data);
+ break;
+ default:
+ return (EINVAL);
}
+ off += bpp;
}
- break;
- case 32: /* 32 bit */
- for (i = 0; i < height; i++) {
- fb32 = (uint32_t *)(fb + i * pitch);
- for (j = 0; j < width; j++)
- fb32[j] = data;
- }
- break;
- default:
- return (1);
}
return (0);
}
static int
-gfx_fb_cons_clear(struct vis_consclear *ca)
+gfxfb_blt_video_to_buffer(void *BltBuffer, uint32_t SourceX, uint32_t SourceY,
+ uint32_t DestinationX, uint32_t DestinationY,
+ uint32_t Width, uint32_t Height, uint32_t Delta)
{
- uint32_t data, width, height;
- int ret;
-#if defined(EFI)
- EFI_TPL tpl;
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p;
+#else
+ struct paletteentry *p;
#endif
+ uint32_t x, sy, dy;
+ uint32_t bpp, pitch, copybytes;
+ off_t off;
+ uint8_t *source, *destination, *sb;
+ uint8_t rm, rp, gm, gp, bm, bp;
+ bool bgra;
+
+ if (BltBuffer == NULL)
+ return (EINVAL);
- data = gfx_fb_color_map(ca->bg_color);
- width = gfx_fb.framebuffer_common.framebuffer_width;
- height = gfx_fb.framebuffer_common.framebuffer_height;
+ if (SourceY + Height >
+ gfx_fb.framebuffer_common.framebuffer_height)
+ return (EINVAL);
-#if defined(EFI)
- tpl = BS->RaiseTPL(TPL_NOTIFY);
-#endif
- ret = gfx_fb_ops.gfx_cons_clear(data, width, height);
-#if defined(EFI)
- BS->RestoreTPL(tpl);
-#endif
- return (ret);
+ if (SourceX + Width > gfx_fb.framebuffer_common.framebuffer_width)
+ return (EINVAL);
+
+ if (Width == 0 || Height == 0)
+ return (EINVAL);
+
+ if (Delta == 0)
+ Delta = Width * sizeof (*p);
+
+ bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
+ pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
+
+ copybytes = Width * bpp;
+
+ rm = (1 << gfx_fb.u.fb2.framebuffer_red_mask_size) - 1;
+ rp = gfx_fb.u.fb2.framebuffer_red_field_position;
+ gm = (1 << gfx_fb.u.fb2.framebuffer_green_mask_size) - 1;
+ gp = gfx_fb.u.fb2.framebuffer_green_field_position;
+ bm = (1 << gfx_fb.u.fb2.framebuffer_blue_mask_size) - 1;
+ bp = gfx_fb.u.fb2.framebuffer_blue_field_position;
+ /* If FB pixel format is BGRA, we can use direct copy. */
+ bgra = bpp == 4 &&
+ gfx_fb.u.fb2.framebuffer_red_mask_size == 8 &&
+ gfx_fb.u.fb2.framebuffer_red_field_position == 16 &&
+ gfx_fb.u.fb2.framebuffer_green_mask_size == 8 &&
+ gfx_fb.u.fb2.framebuffer_green_field_position == 8 &&
+ gfx_fb.u.fb2.framebuffer_blue_mask_size == 8 &&
+ gfx_fb.u.fb2.framebuffer_blue_field_position == 0;
+
+ for (sy = SourceY, dy = DestinationY; dy < Height + DestinationY;
+ sy++, dy++) {
+ off = sy * pitch + SourceX * bpp;
+ source = gfx_get_fb_address() + off;
+ destination = (uint8_t *)BltBuffer + dy * Delta +
+ DestinationX * sizeof (*p);
+
+ if (bgra) {
+ bcopy(source, destination, copybytes);
+ } else {
+ for (x = 0; x < Width; x++) {
+ uint32_t c = 0;
+
+ p = (void *)(destination + x * sizeof (*p));
+ sb = source + x * bpp;
+ switch (bpp) {
+ case 1:
+ c = *sb;
+ break;
+ case 2:
+ c = *(uint16_t *)sb;
+ break;
+ case 3:
+ c = sb[0] << 16 | sb[1] << 8 | sb[2];
+ break;
+ case 4:
+ c = *(uint32_t *)sb;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (bpp == 1) {
+ *(uint32_t *)p = gfx_fb_color_map(
+ (c < NCOLORS) ?
+ pc_color_to_solaris_color[c] : c);
+ } else {
+ p->Red = (c >> rp) & rm;
+ p->Green = (c >> gp) & gm;
+ p->Blue = (c >> bp) & bm;
+ p->Reserved = 0;
+ }
+ }
+ }
+ }
+
+ return (0);
}
-#if defined(EFI)
-static void
-gfx_gop_cons_copy(struct vis_conscopy *ma)
+static int
+gfxfb_blt_buffer_to_video(void *BltBuffer, uint32_t SourceX, uint32_t SourceY,
+ uint32_t DestinationX, uint32_t DestinationY,
+ uint32_t Width, uint32_t Height, uint32_t Delta)
{
- UINTN width, height;
- extern EFI_GRAPHICS_OUTPUT *gop;
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p;
+#else
+ struct paletteentry *p;
+#endif
+ uint32_t x, sy, dy;
+ uint32_t bpp, pitch, copybytes;
+ off_t off;
+ uint8_t *source, *destination;
+ uint8_t rm, rp, gm, gp, bm, bp;
+ bool bgra;
+
+ if (BltBuffer == NULL)
+ return (EINVAL);
- width = ma->e_col - ma->s_col + 1;
- height = ma->e_row - ma->s_row + 1;
+ if (DestinationY + Height >
+ gfx_fb.framebuffer_common.framebuffer_height)
+ return (EINVAL);
- (void) gop->Blt(gop, NULL, EfiBltVideoToVideo, ma->s_col, ma->s_row,
- ma->t_col, ma->t_row, width, height, 0);
+ if (DestinationX + Width > gfx_fb.framebuffer_common.framebuffer_width)
+ return (EINVAL);
+
+ if (Width == 0 || Height == 0)
+ return (EINVAL);
+
+ if (Delta == 0)
+ Delta = Width * sizeof (*p);
+
+ bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
+ pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
+
+ copybytes = Width * bpp;
+
+ rm = (1 << gfx_fb.u.fb2.framebuffer_red_mask_size) - 1;
+ rp = gfx_fb.u.fb2.framebuffer_red_field_position;
+ gm = (1 << gfx_fb.u.fb2.framebuffer_green_mask_size) - 1;
+ gp = gfx_fb.u.fb2.framebuffer_green_field_position;
+ bm = (1 << gfx_fb.u.fb2.framebuffer_blue_mask_size) - 1;
+ bp = gfx_fb.u.fb2.framebuffer_blue_field_position;
+ /* If FB pixel format is BGRA, we can use direct copy. */
+ bgra = bpp == 4 &&
+ gfx_fb.u.fb2.framebuffer_red_mask_size == 8 &&
+ gfx_fb.u.fb2.framebuffer_red_field_position == 16 &&
+ gfx_fb.u.fb2.framebuffer_green_mask_size == 8 &&
+ gfx_fb.u.fb2.framebuffer_green_field_position == 8 &&
+ gfx_fb.u.fb2.framebuffer_blue_mask_size == 8 &&
+ gfx_fb.u.fb2.framebuffer_blue_field_position == 0;
+
+ for (sy = SourceY, dy = DestinationY; sy < Height + SourceY;
+ sy++, dy++) {
+ off = dy * pitch + DestinationX * bpp;
+ destination = gfx_get_fb_address() + off;
+
+ if (bgra) {
+ source = (uint8_t *)BltBuffer + sy * Delta +
+ SourceX * sizeof (*p);
+ bcopy(source, destination, copybytes);
+ } else {
+ for (x = 0; x < Width; x++) {
+ uint32_t c;
+
+ p = (void *)((uint8_t *)BltBuffer +
+ sy * Delta +
+ (SourceX + x) * sizeof (*p));
+ if (bpp == 1) {
+ c = rgb_to_color_index(p->Red,
+ p->Green, p->Blue);
+ } else {
+ c = (p->Red & rm) << rp |
+ (p->Green & gm) << gp |
+ (p->Blue & bm) << bp;
+ }
+ off = x * bpp;
+ switch (bpp) {
+ case 1:
+ gfx_mem_wr1(destination, copybytes,
+ off, (c < NCOLORS) ?
+ solaris_color_to_pc_color[c] : c);
+ break;
+ case 2:
+ gfx_mem_wr2(destination, copybytes,
+ off, c);
+ break;
+ case 3:
+ gfx_mem_wr1(destination, copybytes,
+ off, (c >> 16) & 0xff);
+ gfx_mem_wr1(destination, copybytes,
+ off + 1, (c >> 8) & 0xff);
+ gfx_mem_wr1(destination, copybytes,
+ off + 2, c & 0xff);
+ break;
+ case 4:
+ gfx_mem_wr4(destination, copybytes,
+ off, c);
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
+ }
+ }
+
+ return (0);
}
-#endif
-static void
-gfx_bm_cons_copy(struct vis_conscopy *ma)
+static int
+gfxfb_blt_video_to_video(uint32_t SourceX, uint32_t SourceY,
+ uint32_t DestinationX, uint32_t DestinationY,
+ uint32_t Width, uint32_t Height)
{
- uint32_t soffset, toffset;
- uint32_t width, height;
- uint8_t *src, *dst, *fb;
- uint32_t bpp, pitch;
+ uint32_t bpp, copybytes;
+ int pitch;
+ uint8_t *source, *destination;
+ off_t off;
+
+ if (SourceY + Height >
+ gfx_fb.framebuffer_common.framebuffer_height)
+ return (EINVAL);
+
+ if (SourceX + Width > gfx_fb.framebuffer_common.framebuffer_width)
+ return (EINVAL);
+
+ if (DestinationY + Height >
+ gfx_fb.framebuffer_common.framebuffer_height)
+ return (EINVAL);
+
+ if (DestinationX + Width > gfx_fb.framebuffer_common.framebuffer_width)
+ return (EINVAL);
+
+ if (Width == 0 || Height == 0)
+ return (EINVAL);
- fb = gfx_get_fb_address();
bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
- soffset = ma->s_col * bpp + ma->s_row * pitch;
- toffset = ma->t_col * bpp + ma->t_row * pitch;
- src = fb + soffset;
- dst = fb + toffset;
- width = (ma->e_col - ma->s_col + 1) * bpp;
- height = ma->e_row - ma->s_row + 1;
+ copybytes = Width * bpp;
- if (toffset <= soffset) {
- for (uint32_t i = 0; i < height; i++) {
- uint32_t increment = i * pitch;
- (void) memmove(dst + increment, src + increment, width);
+ off = SourceY * pitch + SourceX * bpp;
+ source = gfx_get_fb_address() + off;
+ off = DestinationY * pitch + DestinationX * bpp;
+ destination = gfx_get_fb_address() + off;
+
+ /*
+ * To handle overlapping areas, set up reverse copy here.
+ */
+ if ((uintptr_t)destination > (uintptr_t)source) {
+ source += Height * pitch;
+ destination += Height * pitch;
+ pitch = -pitch;
+ }
+
+ while (Height-- > 0) {
+ bcopy(source, destination, copybytes);
+ source += pitch;
+ destination += pitch;
+ }
+
+ return (0);
+}
+
+int
+gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation,
+ uint32_t SourceX, uint32_t SourceY,
+ uint32_t DestinationX, uint32_t DestinationY,
+ uint32_t Width, uint32_t Height, uint32_t Delta)
+{
+ int rv;
+#if defined(EFI)
+ EFI_STATUS status;
+ extern EFI_GRAPHICS_OUTPUT *gop;
+
+ /*
+ * We assume Blt() does work, if not, we will need to build
+ * exception list case by case.
+ */
+ if (gop != NULL) {
+ switch (BltOperation) {
+ case GfxFbBltVideoFill:
+ status = gop->Blt(gop, BltBuffer, EfiBltVideoFill,
+ SourceX, SourceY, DestinationX, DestinationY,
+ Width, Height, Delta);
+ break;
+
+ case GfxFbBltVideoToBltBuffer:
+ status = gop->Blt(gop, BltBuffer,
+ EfiBltVideoToBltBuffer,
+ SourceX, SourceY, DestinationX, DestinationY,
+ Width, Height, Delta);
+ break;
+
+ case GfxFbBltBufferToVideo:
+ status = gop->Blt(gop, BltBuffer, EfiBltBufferToVideo,
+ SourceX, SourceY, DestinationX, DestinationY,
+ Width, Height, Delta);
+ break;
+
+ case GfxFbBltVideoToVideo:
+ status = gop->Blt(gop, BltBuffer, EfiBltVideoToVideo,
+ SourceX, SourceY, DestinationX, DestinationY,
+ Width, Height, Delta);
+ break;
+
+ default:
+ status = EFI_INVALID_PARAMETER;
+ break;
}
- } else {
- for (int i = height - 1; i >= 0; i--) {
- uint32_t increment = i * pitch;
- (void) memmove(dst + increment, src + increment, width);
+
+ switch (status) {
+ case EFI_SUCCESS:
+ rv = 0;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ rv = EINVAL;
+ break;
+
+ case EFI_DEVICE_ERROR:
+ default:
+ rv = EIO;
+ break;
}
+
+ return (rv);
}
+#endif
+
+ switch (BltOperation) {
+ case GfxFbBltVideoFill:
+ rv = gfxfb_blt_fill(BltBuffer, DestinationX, DestinationY,
+ Width, Height);
+ break;
+
+ case GfxFbBltVideoToBltBuffer:
+ rv = gfxfb_blt_video_to_buffer(BltBuffer, SourceX, SourceY,
+ DestinationX, DestinationY, Width, Height, Delta);
+ break;
+
+ case GfxFbBltBufferToVideo:
+ rv = gfxfb_blt_buffer_to_video(BltBuffer, SourceX, SourceY,
+ DestinationX, DestinationY, Width, Height, Delta);
+ break;
+
+ case GfxFbBltVideoToVideo:
+ rv = gfxfb_blt_video_to_video(SourceX, SourceY,
+ DestinationX, DestinationY, Width, Height);
+ break;
+
+ default:
+ rv = EINVAL;
+ break;
+ }
+ return (rv);
}
-static void
+/*
+ * visual io callbacks.
+ */
+int
+gfx_fb_cons_clear(struct vis_consclear *ca)
+{
+ int rv;
+ uint32_t data, width, height;
+#if defined(EFI)
+ EFI_TPL tpl;
+#endif
+
+ data = gfx_fb_color_map(ca->bg_color);
+ width = gfx_fb.framebuffer_common.framebuffer_width;
+ height = gfx_fb.framebuffer_common.framebuffer_height;
+
+#if defined(EFI)
+ tpl = BS->RaiseTPL(TPL_NOTIFY);
+#endif
+ rv = gfxfb_blt(&data, GfxFbBltVideoFill, 0, 0,
+ 0, 0, width, height, 0);
+#if defined(EFI)
+ BS->RestoreTPL(tpl);
+#endif
+
+ return (rv);
+}
+
+void
gfx_fb_cons_copy(struct vis_conscopy *ma)
{
-#if defined(EFI)
+ uint32_t width, height;
+#if defined(EFI)
EFI_TPL tpl;
tpl = BS->RaiseTPL(TPL_NOTIFY);
#endif
- gfx_fb_ops.gfx_cons_copy(ma);
-#if defined(EFI)
+ width = ma->e_col - ma->s_col + 1;
+ height = ma->e_row - ma->s_row + 1;
+
+ (void) gfxfb_blt(NULL, GfxFbBltVideoToVideo, ma->s_col, ma->s_row,
+ ma->t_col, ma->t_row, width, height, 0);
+#if defined(EFI)
BS->RestoreTPL(tpl);
#endif
}
@@ -600,103 +1026,57 @@ alpha_blend(uint8_t fg, uint8_t bg, uint8_t alpha)
/* Copy memory to framebuffer or to memory. */
static void
-bitmap_cpy(uint8_t *dst, uint8_t *src, uint32_t len, int bpp)
+bitmap_cpy(void *dst, void *src, size_t size)
{
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ps, *pd;
+#else
+ struct paletteentry *ps, *pd;
+#endif
uint32_t i;
uint8_t a;
- switch (bpp) {
- case 4:
- /*
- * we only implement alpha blending for depth 32,
- * use memcpy for other cases.
- */
- for (i = 0; i < len; i += bpp) {
- a = src[i+3];
- dst[i] = alpha_blend(src[i], dst[i], a);
- dst[i+1] = alpha_blend(src[i+1], dst[i+1], a);
- dst[i+2] = alpha_blend(src[i+2], dst[i+2], a);
- dst[i+3] = a;
- }
- break;
- default:
- (void) memcpy(dst, src, len);
- break;
- }
-}
-
-#if defined(EFI)
-static void
-gfx_gop_cons_display(struct vis_consdisplay *da)
-{
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
- uint32_t size;
- int bpp;
- extern EFI_GRAPHICS_OUTPUT *gop;
-
- bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
- size = sizeof (*BltBuffer) * da->width * da->height;
+ ps = src;
+ pd = dst;
/*
- * Common data to display is glyph, use preallocated
- * glyph buffer.
+ * we only implement alpha blending for depth 32.
*/
- if (size == GlyphBufferSize) {
- BltBuffer = GlyphBuffer;
- } else {
- BltBuffer = malloc(size);
+ for (i = 0; i < size; i++) {
+ a = ps[i].Reserved;
+ pd[i].Red = alpha_blend(ps[i].Red, pd[i].Red, a);
+ pd[i].Green = alpha_blend(ps[i].Green, pd[i].Green, a);
+ pd[i].Blue = alpha_blend(ps[i].Blue, pd[i].Blue, a);
+ pd[i].Reserved = a;
}
- if (BltBuffer == NULL) {
- if (gfx_get_fb_address() != NULL) {
- /* Fall back to bitmap implementation */
- gfx_bm_cons_display(da);
- }
- /*
- * We can not use Blt() and we have no address
- * to write data to FB.
- */
- return;
- }
-
- (void) gop->Blt(gop, BltBuffer, EfiBltVideoToBltBuffer,
- da->col, da->row, 0, 0, da->width, da->height, 0);
- bitmap_cpy((void *)BltBuffer, da->data, size, bpp);
- (void) gop->Blt(gop, BltBuffer, EfiBltBufferToVideo,
- 0, 0, da->col, da->row, da->width, da->height, 0);
-
- if (BltBuffer != GlyphBuffer)
- free(BltBuffer);
}
-#endif
-static void
-gfx_bm_cons_display(struct vis_consdisplay *da)
+static void *
+allocate_glyphbuffer(uint32_t width, uint32_t height)
{
- uint32_t size; /* write size per scanline */
- uint8_t *fbp; /* fb + calculated offset */
- int i, bpp, pitch;
-
- bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
- pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
-
- size = da->width * bpp;
- fbp = gfx_get_fb_address();
- fbp += da->col * bpp + da->row * pitch;
+ size_t size;
- /* write all scanlines in rectangle */
- for (i = 0; i < da->height; i++) {
- uint8_t *dest = fbp + i * pitch;
- uint8_t *src = da->data + i * size;
- bitmap_cpy(dest, src, size, bpp);
+ size = sizeof (*GlyphBuffer) * width * height;
+ if (size != GlyphBufferSize) {
+ free(GlyphBuffer);
+ GlyphBuffer = malloc(size);
+ if (GlyphBuffer == NULL)
+ return (NULL);
+ GlyphBufferSize = size;
}
+ return (GlyphBuffer);
}
-static void
+void
gfx_fb_cons_display(struct vis_consdisplay *da)
{
-#if defined(EFI)
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
EFI_TPL tpl;
+#else
+ struct paletteentry *BltBuffer;
#endif
+ uint32_t size;
/* make sure we will not write past FB */
if ((uint32_t)da->col >= gfx_fb.framebuffer_common.framebuffer_width ||
@@ -707,74 +1087,51 @@ gfx_fb_cons_display(struct vis_consdisplay *da)
gfx_fb.framebuffer_common.framebuffer_height)
return;
-#if defined(EFI)
- tpl = BS->RaiseTPL(TPL_NOTIFY);
-#endif
- gfx_fb_ops.gfx_cons_display(da);
-#if defined(EFI)
- BS->RestoreTPL(tpl);
-#endif
-}
+ size = sizeof (*BltBuffer) * da->width * da->height;
-void
-gfx_fb_display_cursor(struct vis_conscursor *ca)
-{
-#if defined(EFI)
- EFI_TPL tpl;
+ /*
+ * Common data to display is glyph, use preallocated
+ * glyph buffer.
+ */
+ if (tems.ts_pix_data_size != GlyphBufferSize)
+ (void) allocate_glyphbuffer(da->width, da->height);
+
+ if (size == GlyphBufferSize) {
+ BltBuffer = GlyphBuffer;
+ } else {
+ BltBuffer = malloc(size);
+ }
+ if (BltBuffer == NULL)
+ return;
+#if defined(EFI)
tpl = BS->RaiseTPL(TPL_NOTIFY);
#endif
- gfx_fb_ops.gfx_cons_display_cursor(ca);
-#if defined(EFI)
+ if (gfxfb_blt(BltBuffer, GfxFbBltVideoToBltBuffer,
+ da->col, da->row, 0, 0, da->width, da->height, 0) == 0) {
+ bitmap_cpy(BltBuffer, da->data, da->width * da->height);
+ (void) gfxfb_blt(BltBuffer, GfxFbBltBufferToVideo,
+ 0, 0, da->col, da->row, da->width, da->height, 0);
+ }
+
+#if defined(EFI)
BS->RestoreTPL(tpl);
#endif
+ if (BltBuffer != GlyphBuffer)
+ free(BltBuffer);
}
-#if defined(EFI)
static void
-gfx_gop_display_cursor(struct vis_conscursor *ca)
+gfx_fb_cursor_impl(uint32_t fg, uint32_t bg, struct vis_conscursor *ca)
{
union pixel {
+#if defined(EFI)
EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
+#else
+ struct paletteentry p;
+#endif
uint32_t p32;
- } *row, fg, bg;
- size_t size;
- extern EFI_GRAPHICS_OUTPUT *gop;
-
- size = sizeof (*GlyphBuffer) * ca->width * ca->height;
- if (size != GlyphBufferSize) {
- free(GlyphBuffer);
- GlyphBuffer = malloc(size);
- if (GlyphBuffer == NULL) {
- if (gfx_get_fb_address() != NULL) {
- /* Fall back to bitmap implementation */
- gfx_bm_display_cursor(ca);
- }
- /*
- * We can not use Blt() and we have no address
- * to write data to FB.
- */
- return;
- }
- GlyphBufferSize = size;
- }
-
- /*
- * Since EfiBltVideoToBltBuffer is valid, Blt() can fail only
- * due to device error.
- */
- if (gop->Blt(gop, GlyphBuffer, EfiBltVideoToBltBuffer,
- ca->col, ca->row, 0, 0, ca->width, ca->height, 0) != EFI_SUCCESS)
- return;
-
- fg.p.Reserved = 0;
- fg.p.Red = ca->fg_color.twentyfour[0];
- fg.p.Green = ca->fg_color.twentyfour[1];
- fg.p.Blue = ca->fg_color.twentyfour[2];
- bg.p.Reserved = 0;
- bg.p.Red = ca->bg_color.twentyfour[0];
- bg.p.Green = ca->bg_color.twentyfour[1];
- bg.p.Blue = ca->bg_color.twentyfour[2];
+ } *row;
/*
* Build inverse image of the glyph.
@@ -784,94 +1141,49 @@ gfx_gop_display_cursor(struct vis_conscursor *ca)
for (screen_size_t i = 0; i < ca->height; i++) {
row = (union pixel *)(GlyphBuffer + i * ca->width);
for (screen_size_t j = 0; j < ca->width; j++) {
- row[j].p32 = (row[j].p32 ^ fg.p32) ^ bg.p32;
+ row[j].p32 = (row[j].p32 ^ fg) ^ bg;
}
}
-
- (void) gop->Blt(gop, GlyphBuffer, EfiBltBufferToVideo,
- 0, 0, ca->col, ca->row, ca->width, ca->height, 0);
}
-#endif
-static void
-gfx_bm_display_cursor(struct vis_conscursor *ca)
+void
+gfx_fb_display_cursor(struct vis_conscursor *ca)
{
- uint32_t fg, bg;
- uint32_t offset, size, *fb32;
- uint16_t *fb16;
- uint8_t *fb8, *fb;
- uint32_t bpp, pitch;
+ union pixel {
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
+#else
+ struct paletteentry p;
+#endif
+ uint32_t p32;
+ } fg, bg;
+#if defined(EFI)
+ EFI_TPL tpl;
- fb = gfx_get_fb_address();
- bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
- pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
+ tpl = BS->RaiseTPL(TPL_NOTIFY);
+#endif
+
+ fg.p.Reserved = 0;
+ fg.p.Red = ca->fg_color.twentyfour[0];
+ fg.p.Green = ca->fg_color.twentyfour[1];
+ fg.p.Blue = ca->fg_color.twentyfour[2];
+ bg.p.Reserved = 0;
+ bg.p.Red = ca->bg_color.twentyfour[0];
+ bg.p.Green = ca->bg_color.twentyfour[1];
+ bg.p.Blue = ca->bg_color.twentyfour[2];
- size = ca->width * bpp;
+ if (allocate_glyphbuffer(ca->width, ca->height) != NULL) {
+ if (gfxfb_blt(GlyphBuffer, GfxFbBltVideoToBltBuffer,
+ ca->col, ca->row, 0, 0, ca->width, ca->height, 0) == 0)
+ gfx_fb_cursor_impl(fg.p32, bg.p32, ca);
- /*
- * Build cursor image. We are building mirror image of data on
- * frame buffer by (D xor FG) xor BG.
- */
- offset = ca->col * bpp + ca->row * pitch;
- switch (gfx_fb.framebuffer_common.framebuffer_bpp) {
- case 8: /* 8 bit */
- fg = ca->fg_color.mono;
- bg = ca->bg_color.mono;
- for (int i = 0; i < ca->height; i++) {
- fb8 = fb + offset + i * pitch;
- for (uint32_t j = 0; j < size; j += 1) {
- fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff);
- }
- }
- break;
- case 15:
- case 16: /* 16 bit */
- fg = ca->fg_color.sixteen[0] << 8;
- fg |= ca->fg_color.sixteen[1];
- bg = ca->bg_color.sixteen[0] << 8;
- bg |= ca->bg_color.sixteen[1];
- for (int i = 0; i < ca->height; i++) {
- fb16 = (uint16_t *)(fb + offset + i * pitch);
- for (int j = 0; j < ca->width; j++) {
- fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^
- (bg & 0xffff);
- }
- }
- break;
- case 24: /* 24 bit */
- fg = ca->fg_color.twentyfour[0] << 16;
- fg |= ca->fg_color.twentyfour[1] << 8;
- fg |= ca->fg_color.twentyfour[2];
- bg = ca->bg_color.twentyfour[0] << 16;
- bg |= ca->bg_color.twentyfour[1] << 8;
- bg |= ca->bg_color.twentyfour[2];
-
- for (int i = 0; i < ca->height; i++) {
- fb8 = fb + offset + i * pitch;
- for (uint32_t j = 0; j < size; j += 3) {
- fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^
- ((bg >> 16) & 0xff);
- fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^
- ((bg >> 8) & 0xff);
- fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^
- (bg & 0xff);
- }
- }
- break;
- case 32: /* 32 bit */
- fg = ca->fg_color.twentyfour[0] << 16;
- fg |= ca->fg_color.twentyfour[1] << 8;
- fg |= ca->fg_color.twentyfour[2];
- bg = ca->bg_color.twentyfour[0] << 16;
- bg |= ca->bg_color.twentyfour[1] << 8;
- bg |= ca->bg_color.twentyfour[2];
- for (int i = 0; i < ca->height; i++) {
- fb32 = (uint32_t *)(fb + offset + i * pitch);
- for (int j = 0; j < ca->width; j++)
- fb32[j] = (fb32[j] ^ fg) ^ bg;
- }
- break;
+ (void) gfxfb_blt(GlyphBuffer, GfxFbBltBufferToVideo, 0, 0,
+ ca->col, ca->row, ca->width, ca->height, 0);
}
+
+#if defined(EFI)
+ BS->RestoreTPL(tpl);
+#endif
}
/*
@@ -903,13 +1215,8 @@ isqrt(int num)
void
gfx_fb_setpixel(uint32_t x, uint32_t y)
{
- uint32_t c, offset, pitch, bpp;
- uint8_t *fb;
+ uint32_t c;
text_color_t fg, bg;
-#if defined(EFI)
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
- extern EFI_GRAPHICS_OUTPUT *gop;
-#endif
if (plat_stdout_is_framebuffer() == 0)
return;
@@ -921,38 +1228,7 @@ gfx_fb_setpixel(uint32_t x, uint32_t y)
y >= gfx_fb.framebuffer_common.framebuffer_height)
return;
- fb = gfx_get_fb_address();
- pitch = gfx_fb.framebuffer_common.framebuffer_pitch;
- bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
-
- offset = y * pitch + x * bpp;
- switch (gfx_fb.framebuffer_common.framebuffer_bpp) {
- case 8:
- fb[offset] = c & 0xff;
- break;
- case 15:
- case 16:
- *(uint16_t *)(fb + offset) = c & 0xffff;
- break;
- case 24:
- fb[offset] = (c >> 16) & 0xff;
- fb[offset + 1] = (c >> 8) & 0xff;
- fb[offset + 2] = c & 0xff;
- break;
- case 32:
-#if defined(EFI)
- if (gop != NULL) {
- p.Reserved = 0;
- p.Red = (c >> 16) & 0xff;
- p.Green = (c >> 8) & 0xff;
- p.Blue = c & 0xff;
- gop->Blt(gop, &p, EfiBltBufferToVideo, 0, 0,
- x, y, 1, 1, 0);
- } else
-#endif
- *(uint32_t *)(fb + offset) = c;
- break;
- }
+ gfxfb_blt(&c, GfxFbBltVideoFill, 0, 0, x, y, 1, 1, 0);
}
/*
@@ -1203,9 +1479,13 @@ int
gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2,
uint32_t uy2, uint32_t flags)
{
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p;
+#else
+ struct paletteentry *p;
+#endif
struct vis_consdisplay da;
- uint32_t i, j, x, y, fheight, fwidth, color;
- int fbpp;
+ uint32_t i, j, x, y, fheight, fwidth;
uint8_t r, g, b, a;
bool scale = false;
bool trace = false;
@@ -1333,9 +1613,8 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2,
if ((flags & FL_PUTIMAGE_BORDER))
gfx_fb_drawrect(ux1, uy1, ux2, uy2, 0);
- fbpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
-
- da.data = malloc(fwidth * fheight * fbpp);
+ da.data = malloc(fwidth * fheight * sizeof (*p));
+ p = (void *)da.data;
if (da.data == NULL) {
if (trace)
printf("Out of memory.\n");
@@ -1375,7 +1654,7 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2,
uint32_t offset_x1 = offset_x + 1;
/* Target pixel index */
- j = (y * fwidth + x) * fbpp;
+ j = y * fwidth + x;
if (!scale) {
i = GETPIXEL(x, y);
@@ -1425,88 +1704,19 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2,
a = pixel[3];
}
- color =
- r >> (8 - gfx_fb.u.fb2.framebuffer_red_mask_size)
- << gfx_fb.u.fb2.framebuffer_red_field_position |
- g >> (8 - gfx_fb.u.fb2.framebuffer_green_mask_size)
- << gfx_fb.u.fb2.framebuffer_green_field_position |
- b >> (8 - gfx_fb.u.fb2.framebuffer_blue_mask_size)
- << gfx_fb.u.fb2.framebuffer_blue_field_position;
-
- switch (gfx_fb.framebuffer_common.framebuffer_bpp) {
-#if !defined(EFI)
- case 8: {
- uint32_t best, dist, k;
- int diff;
-
- /* if alpha is 0, use screen bg color */
- if (a == 0) {
- text_color_t fg, bg;
-
- tem_get_colors(
- (tem_vt_state_t)tems.ts_active,
- &fg, &bg);
- da.data[j] = gfx_fb_color_map(bg);
- break;
- }
+ if (trace)
+ printf("r/g/b: %x/%x/%x\n", r, g, b);
+ /*
+ * Rough colorspace reduction for 15/16 bit colors.
+ */
+ p[j].Red = r >>
+ (8 - gfx_fb.u.fb2.framebuffer_red_mask_size);
+ p[j].Green = g >>
+ (8 - gfx_fb.u.fb2.framebuffer_green_mask_size);
+ p[j].Blue = b >>
+ (8 - gfx_fb.u.fb2.framebuffer_blue_mask_size);
+ p[j].Reserved = a;
- color = 0;
- best = CMAP_SIZE * CMAP_SIZE * CMAP_SIZE;
- for (k = 0; k < CMAP_SIZE; k++) {
- diff = r - pe8[k].Red;
- dist = diff * diff;
- diff = g - pe8[k].Green;
- dist += diff * diff;
- diff = b - pe8[k].Blue;
- dist += diff * diff;
-
- if (dist == 0)
- break;
-
- if (dist < best) {
- color = k;
- best = dist;
- }
- }
- if (k == CMAP_SIZE)
- k = color;
- da.data[j] = (k < 16) ?
- solaris_color_to_pc_color[k] : k;
- break;
- }
- case 15:
- case 16:
- /* if alpha is 0, use screen bg color */
- if (a == 0) {
- text_color_t fg, bg;
-
- tem_get_colors(
- (tem_vt_state_t)tems.ts_active,
- &fg, &bg);
- color = gfx_fb_color_map(bg);
- }
- *(uint16_t *)(da.data+j) = color;
- break;
- case 24:
- /* if alpha is 0, use screen bg color */
- if (a == 0) {
- text_color_t fg, bg;
-
- tem_get_colors(
- (tem_vt_state_t)tems.ts_active,
- &fg, &bg);
- color = gfx_fb_color_map(bg);
- }
- da.data[j] = ((uint8_t *)&color)[0];
- da.data[j + 1] = ((uint8_t *)&color)[1];
- da.data[j + 2] = ((uint8_t *)&color)[2];
- break;
-#endif
- case 32:
- color |= a << 24;
- *(uint32_t *)(da.data+j) = color;
- break;
- }
wc += wcstep;
}
hc += hcstep;
diff --git a/usr/src/boot/sys/boot/common/gfx_fb.h b/usr/src/boot/sys/boot/common/gfx_fb.h
index 04bbd91121..3fb7fcc3af 100644
--- a/usr/src/boot/sys/boot/common/gfx_fb.h
+++ b/usr/src/boot/sys/boot/common/gfx_fb.h
@@ -133,10 +133,24 @@ typedef TAILQ_HEAD(edid_resolution, resolution) edid_res_list_t;
extern multiboot_tag_framebuffer_t gfx_fb;
+typedef enum {
+ GfxFbBltVideoFill,
+ GfxFbBltVideoToBltBuffer,
+ GfxFbBltBufferToVideo,
+ GfxFbBltVideoToVideo,
+ GfxFbBltOperationMax,
+} GFXFB_BLT_OPERATION;
+
+int gfxfb_blt(void *, GFXFB_BLT_OPERATION, uint32_t, uint32_t,
+ uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+
void bios_text_font(bool);
bool gfx_get_edid_resolution(struct vesa_edid_info *, edid_res_list_t *);
-void gfx_framework_init(struct visual_ops *);
+void gfx_framework_init(void);
uint32_t gfx_fb_color_map(uint8_t);
+int gfx_fb_cons_clear(struct vis_consclear *);
+void gfx_fb_cons_copy(struct vis_conscopy *);
+void gfx_fb_cons_display(struct vis_consdisplay *);
void gfx_fb_display_cursor(struct vis_conscursor *);
void gfx_fb_setpixel(uint32_t, uint32_t);
void gfx_fb_drawrect(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
diff --git a/usr/src/boot/sys/boot/common/tem.c b/usr/src/boot/sys/boot/common/tem.c
index 561be4e28d..ebb3ae48f8 100644
--- a/usr/src/boot/sys/boot/common/tem.c
+++ b/usr/src/boot/sys/boot/common/tem.c
@@ -143,14 +143,6 @@ static void tem_pix_cls_range(struct tem_vt_state *, screen_pos_t, int,
static void tem_pix_cls(struct tem_vt_state *, int,
screen_pos_t, screen_pos_t);
-static void bit_to_pix4(struct tem_vt_state *tem, tem_char_t c,
- text_color_t fg_color, text_color_t bg_color);
-static void bit_to_pix8(struct tem_vt_state *tem, tem_char_t c,
- text_color_t fg_color, text_color_t bg_color);
-static void bit_to_pix16(struct tem_vt_state *tem, tem_char_t c,
- text_color_t fg_color, text_color_t bg_color);
-static void bit_to_pix24(struct tem_vt_state *tem, tem_char_t c,
- text_color_t fg_color, text_color_t bg_color);
static void bit_to_pix32(struct tem_vt_state *tem, tem_char_t c,
text_color_t fg_color, text_color_t bg_color);
@@ -2291,35 +2283,12 @@ static void
tem_pix_bit2pix(struct tem_vt_state *tem, term_char_t c)
{
text_color_t fg, bg;
- void (*fp)(struct tem_vt_state *, tem_char_t,
- unsigned char, unsigned char);
fg = DEFAULT_ANSI_FOREGROUND;
bg = DEFAULT_ANSI_BACKGROUND;
tem_get_color(&fg, &bg, c);
- switch (tems.ts_pdepth) {
- case 4:
- fp = bit_to_pix4;
- break;
- case 8:
- fp = bit_to_pix8;
- break;
- case 15:
- case 16:
- fp = bit_to_pix16;
- break;
- case 24:
- fp = bit_to_pix24;
- break;
- case 32:
- fp = bit_to_pix32;
- break;
- default:
- return;
- }
-
- fp(tem, c.tc_char, fg, bg);
+ bit_to_pix32(tem, c.tc_char, fg, bg);
}
@@ -2657,36 +2626,14 @@ tem_pix_cursor(struct tem_vt_state *tem, short action)
bg = DEFAULT_ANSI_BACKGROUND;
tem_get_color(&fg, &bg, c);
- switch (tems.ts_pdepth) {
- case 4:
- ca.fg_color.mono = fg;
- ca.bg_color.mono = bg;
- break;
- case 8:
- ca.fg_color.mono = tems.ts_color_map(fg);
- ca.bg_color.mono = tems.ts_color_map(bg);
- break;
- case 15:
- case 16:
- color = tems.ts_color_map(fg);
- ca.fg_color.sixteen[0] = (color >> 8) & 0xFF;
- ca.fg_color.sixteen[1] = color & 0xFF;
- color = tems.ts_color_map(bg);
- ca.bg_color.sixteen[0] = (color >> 8) & 0xFF;
- ca.bg_color.sixteen[1] = color & 0xFF;
- break;
- case 24:
- case 32:
- color = tems.ts_color_map(fg);
- ca.fg_color.twentyfour[0] = (color >> 16) & 0xFF;
- ca.fg_color.twentyfour[1] = (color >> 8) & 0xFF;
- ca.fg_color.twentyfour[2] = color & 0xFF;
- color = tems.ts_color_map(bg);
- ca.bg_color.twentyfour[0] = (color >> 16) & 0xFF;
- ca.bg_color.twentyfour[1] = (color >> 8) & 0xFF;
- ca.bg_color.twentyfour[2] = color & 0xFF;
- break;
- }
+ color = tems.ts_color_map(fg);
+ ca.fg_color.twentyfour[0] = (color >> 16) & 0xFF;
+ ca.fg_color.twentyfour[1] = (color >> 8) & 0xFF;
+ ca.fg_color.twentyfour[2] = color & 0xFF;
+ color = tems.ts_color_map(bg);
+ ca.bg_color.twentyfour[0] = (color >> 16) & 0xFF;
+ ca.bg_color.twentyfour[1] = (color >> 8) & 0xFF;
+ ca.bg_color.twentyfour[2] = color & 0xFF;
ca.action = action;
@@ -2708,61 +2655,6 @@ tem_pix_cursor(struct tem_vt_state *tem, short action)
}
static void
-bit_to_pix4(struct tem_vt_state *tem,
- tem_char_t c,
- text_color_t fg_color,
- text_color_t bg_color)
-{
- uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
- font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color);
-}
-
-static void
-bit_to_pix8(struct tem_vt_state *tem,
- tem_char_t c,
- text_color_t fg_color,
- text_color_t bg_color)
-{
- uint8_t *dest = (uint8_t *)tem->tvs_pix_data;
-
- fg_color = (text_color_t)tems.ts_color_map(fg_color);
- bg_color = (text_color_t)tems.ts_color_map(bg_color);
- font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color);
-}
-
-static void
-bit_to_pix16(struct tem_vt_state *tem,
- tem_char_t c,
- text_color_t fg_color4,
- text_color_t bg_color4)
-{
- uint16_t fg_color16, bg_color16;
- uint16_t *dest;
-
- fg_color16 = (uint16_t)tems.ts_color_map(fg_color4);
- bg_color16 = (uint16_t)tems.ts_color_map(bg_color4);
-
- dest = (uint16_t *)tem->tvs_pix_data;
- font_bit_to_pix16(&tems.ts_font, dest, c, fg_color16, bg_color16);
-}
-
-static void
-bit_to_pix24(struct tem_vt_state *tem,
- tem_char_t c,
- text_color_t fg_color4,
- text_color_t bg_color4)
-{
- uint32_t fg_color32, bg_color32;
- uint8_t *dest;
-
- fg_color32 = tems.ts_color_map(fg_color4);
- bg_color32 = tems.ts_color_map(bg_color4);
-
- dest = (uint8_t *)tem->tvs_pix_data;
- font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32);
-}
-
-static void
bit_to_pix32(struct tem_vt_state *tem,
tem_char_t c,
text_color_t fg_color4,
diff --git a/usr/src/boot/sys/boot/efi/libefi/efi_console.c b/usr/src/boot/sys/boot/efi/libefi/efi_console.c
index 37d07a8802..13c2ad0635 100644
--- a/usr/src/boot/sys/boot/efi/libefi/efi_console.c
+++ b/usr/src/boot/sys/boot/efi/libefi/efi_console.c
@@ -124,10 +124,10 @@ struct visual_ops fb_ops = {
.ident = &fb_ident,
.kdsetmode = NULL,
.devinit = efi_fb_devinit,
- .cons_copy = NULL,
- .cons_display = NULL,
+ .cons_copy = gfx_fb_cons_copy,
+ .cons_display = gfx_fb_cons_display,
.cons_cursor = efi_cons_cursor,
- .cons_clear = NULL,
+ .cons_clear = gfx_fb_cons_clear,
.cons_put_cmap = NULL
};
@@ -539,7 +539,7 @@ efi_cons_init(struct console *cp, int arg __unused)
if (status == EFI_SUCCESS)
ecd->ecd_coninex = coninex;
- gfx_framework_init(&fb_ops);
+ gfx_framework_init();
if (tem_info_init(cp) == 0 && tem == NULL) {
tem = tem_init();
diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.c b/usr/src/boot/sys/boot/i386/libi386/vbe.c
index c660367bdf..4f98cdf747 100644
--- a/usr/src/boot/sys/boot/i386/libi386/vbe.c
+++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c
@@ -333,7 +333,7 @@ vbe_set_palette(const struct paletteentry *entry, size_t slot)
pe.Blue = entry->Blue;
pe.Green = entry->Green;
pe.Red = entry->Red;
- pe.Alignment = entry->Alignment;
+ pe.Reserved = entry->Reserved;
if (vbe->Capabilities & VBE_CAP_SNOW)
mode = 0x80;
diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.h b/usr/src/boot/sys/boot/i386/libi386/vbe.h
index c775b13012..e049af1e42 100644
--- a/usr/src/boot/sys/boot/i386/libi386/vbe.h
+++ b/usr/src/boot/sys/boot/i386/libi386/vbe.h
@@ -111,7 +111,7 @@ struct paletteentry {
uint8_t Blue;
uint8_t Green;
uint8_t Red;
- uint8_t Alignment;
+ uint8_t Reserved;
} __packed;
struct flatpanelinfo
diff --git a/usr/src/boot/sys/boot/i386/libi386/vidconsole.c b/usr/src/boot/sys/boot/i386/libi386/vidconsole.c
index 9dff446903..dbdbcbc699 100644
--- a/usr/src/boot/sys/boot/i386/libi386/vidconsole.c
+++ b/usr/src/boot/sys/boot/i386/libi386/vidconsole.c
@@ -108,10 +108,10 @@ struct visual_ops fb_ops = {
.ident = &fb_ident,
.kdsetmode = NULL,
.devinit = vidc_vbe_devinit,
- .cons_copy = NULL,
- .cons_display = NULL,
+ .cons_copy = gfx_fb_cons_copy,
+ .cons_display = gfx_fb_cons_display,
.cons_cursor = vidc_cons_cursor,
- .cons_clear = NULL,
+ .cons_clear = gfx_fb_cons_clear,
.cons_put_cmap = vidc_vbe_cons_put_cmap
};
@@ -570,24 +570,24 @@ vidc_vbe_cons_put_cmap(struct vis_cmap *cm)
rgb.blue.pos = gfx_fb.u.fb2.framebuffer_blue_field_position;
rgb.blue.size = gfx_fb.u.fb2.framebuffer_blue_mask_size;
- /*
- * The first 16 colors need to be in VGA color order.
- */
- for (i = cm->index; i < 256 && rc == 0; i++) {
- if (i < 16) {
- if (i < 15)
- c = rgb_color_map(&rgb, i + 1);
- else
- c = rgb_color_map(&rgb, 0);
- } else {
- c = rgb_color_map(&rgb, i);
- }
+ for (i = cm->index; i < NCMAP && rc == 0; i++) {
+ int idx;
+
+ /* Pick RGB from cmap4_to_24 */
+ c = rgb_color_map(&rgb, i);
+ /* The first 16 colors need to be in VGA color order. */
+ if (i < NCOLORS)
+ idx = solaris_color_to_pc_color[i];
+ else
+ idx = i;
+
pe8[i].Red = (c >> rgb.red.pos) & ((1 << rgb.red.size) - 1);
pe8[i].Green =
(c >> rgb.green.pos) & ((1 << rgb.green.size) - 1);
- pe8[i].Blue = (c >> rgb.blue.pos) & ((1 << rgb.blue.size) - 1);
- pe8[i].Alignment = 0;
- rc = vbe_set_palette(&pe8[i], i);
+ pe8[i].Blue =
+ (c >> rgb.blue.pos) & ((1 << rgb.blue.size) - 1);
+ pe8[i].Reserved = 0;
+ rc = vbe_set_palette(&pe8[i], idx);
}
return (rc);
}
@@ -869,7 +869,7 @@ vidc_init(struct console *cp, int arg)
}
}
- gfx_framework_init(&fb_ops);
+ gfx_framework_init();
/* set up callback before calling tem_info_init(). */
tem_register_modechg_cb(vidc_install_font, (tem_modechg_cb_arg_t)cp);
rc = tem_info_init(cp);
diff --git a/usr/src/boot/sys/sys/tem_impl.h b/usr/src/boot/sys/sys/tem_impl.h
index ee0dcbb28f..6764475695 100644
--- a/usr/src/boot/sys/sys/tem_impl.h
+++ b/usr/src/boot/sys/sys/tem_impl.h
@@ -183,7 +183,7 @@ struct tem_vt_state {
term_char_t *tvs_outbuf; /* place to keep incomplete lines */
int tvs_outindex; /* index into a_outbuf */
void *tvs_pix_data; /* pointer to tmp bitmap area */
- int tvs_pix_data_size;
+ unsigned tvs_pix_data_size;
text_color_t tvs_fg_color;
text_color_t tvs_bg_color;
int tvs_first_line; /* kernel console output begins */
@@ -226,7 +226,7 @@ typedef struct tem_state {
struct tem_size ts_p_dimension; /* screen dimensions in pixels */
struct tem_pix_pos ts_p_offset; /* pix offset to center the display */
- int ts_pix_data_size; /* size of bitmap data areas */
+ unsigned ts_pix_data_size; /* size of bitmap data areas */
int ts_pdepth; /* pixel depth */
struct font ts_font; /* font table */
bool update_font; /* flag the font change */
diff --git a/usr/src/common/font/font.c b/usr/src/common/font/font.c
index 81d5b4ae53..35e2e12eca 100644
--- a/usr/src/common/font/font.c
+++ b/usr/src/common/font/font.c
@@ -62,7 +62,7 @@ const uint8_t solaris_color_to_pc_color[16] = {
pc_magenta, /* 6 - magenta */
pc_brown, /* 7 - brown */
pc_white, /* 8 - white */
- pc_grey, /* 9 - gery */
+ pc_grey, /* 9 - grey */
pc_brt_blue, /* 10 - brt_blue */
pc_brt_green, /* 11 - brt_green */
pc_brt_cyan, /* 12 - brt_cyan */
@@ -71,6 +71,25 @@ const uint8_t solaris_color_to_pc_color[16] = {
pc_yellow /* 15 - yellow */
};
+const uint8_t pc_color_to_solaris_color[16] = {
+ sun_black, /* 0 - black */
+ sun_blue, /* 1 - blue */
+ sun_green, /* 2 - green */
+ sun_cyan, /* 3 - cyan */
+ sun_red, /* 4 - red */
+ sun_magenta, /* 5 - magenta */
+ sun_brown, /* 6 - brown */
+ sun_white, /* 7 - white */
+ sun_grey, /* 8 - grey */
+ sun_brt_blue, /* 9 - brt_blue */
+ sun_brt_green, /* 10 - brt_green */
+ sun_brt_cyan, /* 11 - brt_cyan */
+ sun_brt_red, /* 12 - brt_red */
+ sun_brt_magenta, /* 13 - brt_magenta */
+ sun_yellow, /* 14 - yellow */
+ sun_brt_white /* 15 - brt_white */
+};
+
/* 4-bit to 24-bit color translation. */
const text_cmap_t cmap4_to_24 = {
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
diff --git a/usr/src/uts/common/sys/rgb.h b/usr/src/uts/common/sys/rgb.h
index 9ddfaa9e3f..6e0ba29af2 100644
--- a/usr/src/uts/common/sys/rgb.h
+++ b/usr/src/uts/common/sys/rgb.h
@@ -23,6 +23,13 @@ extern "C" {
#endif
/*
+ * Number of "base" colors is 16, 8 dark and 8 bright/light.
+ * Color map size for indexed colors is 256, to support VGA 256-color modes.
+ */
+#define NCOLORS 16
+#define NCMAP 256
+
+/*
* Color data from bootloader.
*/
typedef struct rgb_color {
@@ -37,9 +44,9 @@ typedef struct rgb {
} rgb_t;
typedef struct {
- uint8_t red[16];
- uint8_t green[16];
- uint8_t blue[16];
+ uint8_t red[NCOLORS];
+ uint8_t green[NCOLORS];
+ uint8_t blue[NCOLORS];
} text_cmap_t;
extern const text_cmap_t cmap4_to_24;
@@ -67,10 +74,30 @@ typedef enum pc_colors {
pc_brt_white = 15
} pc_colors_t;
+typedef enum sun_colors {
+ sun_brt_white = 0,
+ sun_black = 1,
+ sun_blue = 2,
+ sun_green = 3,
+ sun_cyan = 4,
+ sun_red = 5,
+ sun_magenta = 6,
+ sun_brown = 7,
+ sun_white = 8,
+ sun_grey = 9,
+ sun_brt_blue = 10,
+ sun_brt_green = 11,
+ sun_brt_cyan = 12,
+ sun_brt_red = 13,
+ sun_brt_magenta = 14,
+ sun_yellow = 15,
+} sun_colors_t;
+
#define XLATE_NCOLORS 8
extern const uint8_t dim_xlate[XLATE_NCOLORS];
extern const uint8_t brt_xlate[XLATE_NCOLORS];
-extern const uint8_t solaris_color_to_pc_color[16];
+extern const uint8_t solaris_color_to_pc_color[NCOLORS];
+extern const uint8_t pc_color_to_solaris_color[NCOLORS];
extern uint32_t rgb_color_map(const rgb_t *, uint8_t);