diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.c | 1210 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.h | 16 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/common/tem.c | 126 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/efi/libefi/efi_console.c | 8 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vbe.c | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vbe.h | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vidconsole.c | 38 | ||||
-rw-r--r-- | usr/src/boot/sys/sys/tem_impl.h | 4 | ||||
-rw-r--r-- | usr/src/common/font/font.c | 21 | ||||
-rw-r--r-- | usr/src/uts/common/sys/rgb.h | 35 |
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); |