30,7 → 30,7 |
|
/** |
* @defgroup fb Graphical framebuffer |
* @brief HelenOS graphical framebuffer. |
* @brief HelenOS graphical framebuffer. |
* @ingroup fbs |
* @{ |
*/ |
51,13 → 51,10 |
#include <ipc/services.h> |
#include <kernel/errno.h> |
#include <kernel/genarch/fb/visuals.h> |
#include <io/color.h> |
#include <io/style.h> |
#include <console/color.h> |
#include <console/style.h> |
#include <async.h> |
#include <fibril.h> |
#include <bool.h> |
#include <stdio.h> |
#include <byteorder.h> |
|
#include "font-8x16.h" |
#include "fb.h" |
71,8 → 68,6 |
#define DEFAULT_BGCOLOR 0xf0f0f0 |
#define DEFAULT_FGCOLOR 0x000000 |
|
#define GLYPH_UNAVAIL '?' |
|
#define MAX_ANIM_LEN 8 |
#define MAX_ANIMATIONS 4 |
#define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
81,12 → 76,9 |
/** Function to render a pixel from a RGB value. */ |
typedef void (*rgb_conv_t)(void *, uint32_t); |
|
/** Function to render a bit mask. */ |
typedef void (*mask_conv_t)(void *, bool); |
|
/** Function to draw a glyph. */ |
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
struct { |
uint8_t *fb_addr; |
100,16 → 92,12 |
unsigned int pixelbytes; |
unsigned int glyphbytes; |
|
/** Pre-rendered mask for rendering glyphs. Specific for the visual. */ |
uint8_t *glyphs; |
|
rgb_conv_t rgb_conv; |
mask_conv_t mask_conv; |
} screen; |
|
/** Backbuffer character cell. */ |
typedef struct { |
uint32_t glyph; |
uint8_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
} bb_cell_t; |
128,17 → 116,18 |
/* |
* Style and glyphs for text printing |
*/ |
|
|
/** Current attributes. */ |
attr_rgb_t attr; |
|
|
/** Pre-rendered mask for rendering glyphs. Different viewports |
* might use different drawing functions depending on whether their |
* scanlines are aligned on a word boundary.*/ |
uint8_t *glyphs; |
|
uint8_t *bgpixel; |
|
/** |
* Glyph drawing function for this viewport. Different viewports |
* might use different drawing functions depending on whether their |
* scanlines are aligned on a word boundary. |
*/ |
|
/** Glyph drawing function for this viewport. */ |
dg_t dglyph; |
|
/* Auto-cursor position */ |
177,23 → 166,23 |
static bool client_connected = false; /**< Allow only 1 connection */ |
|
static uint32_t color_table[16] = { |
[COLOR_BLACK] = 0x000000, |
[COLOR_BLUE] = 0x0000f0, |
[COLOR_GREEN] = 0x00f000, |
[COLOR_CYAN] = 0x00f0f0, |
[COLOR_RED] = 0xf00000, |
[COLOR_MAGENTA] = 0xf000f0, |
[COLOR_YELLOW] = 0xf0f000, |
[COLOR_WHITE] = 0xf0f0f0, |
|
[8 + COLOR_BLACK] = 0x000000, |
[8 + COLOR_BLUE] = 0x0000ff, |
[8 + COLOR_GREEN] = 0x00ff00, |
[8 + COLOR_CYAN] = 0x00ffff, |
[8 + COLOR_RED] = 0xff0000, |
[8 + COLOR_MAGENTA] = 0xff00ff, |
[8 + COLOR_YELLOW] = 0xffff00, |
[8 + COLOR_WHITE] = 0xffffff, |
[COLOR_BLACK] = 0x000000, |
[COLOR_BLUE] = 0x0000f0, |
[COLOR_GREEN] = 0x00f000, |
[COLOR_CYAN] = 0x00f0f0, |
[COLOR_RED] = 0xf00000, |
[COLOR_MAGENTA] = 0xf000f0, |
[COLOR_YELLOW] = 0xf0f000, |
[COLOR_WHITE] = 0xf0f0f0, |
|
[8 + COLOR_BLACK] = 0x000000, |
[8 + COLOR_BLUE] = 0x0000ff, |
[8 + COLOR_GREEN] = 0x00ff00, |
[8 + COLOR_CYAN] = 0x00ffff, |
[8 + COLOR_RED] = 0xff0000, |
[8 + COLOR_MAGENTA] = 0xff00ff, |
[8 + COLOR_YELLOW] = 0xffff00, |
[8 + COLOR_WHITE] = 0xffffff, |
}; |
|
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a); |
205,17 → 194,17 |
ipcarg_t bg_color, ipcarg_t attr); |
|
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
unsigned int row); |
|
|
#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1)) |
#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1)) |
#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1)) |
#define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1)) |
#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1)) |
|
#define COL2X(col) ((col) * FONT_WIDTH) |
#define ROW2Y(row) ((row) * FONT_SCANLINES) |
227,146 → 216,105 |
#define BB_POS(vport, col, row) ((row) * vport->cols + (col)) |
#define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline) |
|
/* |
* RGB conversion and mask functions. |
|
/** ARGB 8:8:8:8 conversion |
* |
* These functions write an RGB value to some memory in some predefined format. |
* The naming convention corresponds to the format created by these functions. |
* The functions use the so called network order (i.e. big endian) with respect |
* to their names. |
*/ |
|
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) | |
(RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8))); |
*((uint32_t *) dst) = rgb & 0xffffff; |
} |
|
|
/** ABGR 8:8:8:8 conversion |
* |
*/ |
static void bgr_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) | |
(BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8))); |
*((uint32_t *) dst) |
= (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8); |
} |
|
static void mask_0888(void *dst, bool mask) |
{ |
bgr_0888(dst, mask ? 0xffffff : 0); |
} |
|
static void rgb_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) | |
(GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0); |
} |
|
static void bgr_8880(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) | |
(GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0); |
} |
|
static void mask_8880(void *dst, bool mask) |
{ |
bgr_8880(dst, mask ? 0xffffff : 0); |
} |
|
/** RGB 8:8:8 conversion |
* |
*/ |
static void rgb_888(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
|
static void bgr_888(void *dst, uint32_t rgb) |
{ |
((uint8_t *) dst)[0] = BLUE(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
|
static void mask_888(void *dst, bool mask) |
{ |
bgr_888(dst, mask ? 0xffffff : 0); |
} |
|
static void rgb_555_be(void *dst, uint32_t rgb) |
/** BGR 8:8:8 conversion |
* |
*/ |
static void bgr_888(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 | |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); |
((uint8_t *) dst)[0] = RED(rgb, 8); |
((uint8_t *) dst)[1] = GREEN(rgb, 8); |
((uint8_t *) dst)[2] = BLUE(rgb, 8); |
} |
|
static void rgb_555_le(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 | |
GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); |
} |
|
static void rgb_565_be(void *dst, uint32_t rgb) |
/** RGB 5:5:5 conversion |
* |
*/ |
static void rgb_555(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 | |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
|
static void rgb_565_le(void *dst, uint32_t rgb) |
{ |
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 | |
GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); |
} |
|
static void mask_555(void *dst, bool mask) |
/** RGB 5:6:5 conversion |
* |
*/ |
static void rgb_565(void *dst, uint32_t rgb) |
{ |
rgb_555_be(dst, mask ? 0xffffff : 0); |
*((uint16_t *) dst) |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
|
static void mask_565(void *dst, bool mask) |
{ |
rgb_565_be(dst, mask ? 0xffffff : 0); |
} |
|
static void bgr_323(void *dst, uint32_t rgb) |
/** RGB 3:2:3 |
* |
*/ |
static void rgb_323(void *dst, uint32_t rgb) |
{ |
*((uint8_t *) dst) |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
|
static void mask_323(void *dst, bool mask) |
{ |
bgr_323(dst, mask ? 0x0 : ~0x0); |
} |
|
/** Draw a filled rectangle. |
* |
* @note Need real implementation that does not access VRAM twice. |
* |
*/ |
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, |
unsigned int y1, uint32_t color) |
{ |
unsigned int x; |
unsigned int y; |
unsigned int x, y; |
unsigned int copy_bytes; |
|
uint8_t *sp; |
uint8_t *dp; |
|
uint8_t *sp, *dp; |
uint8_t cbuf[4]; |
|
if ((y0 >= y1) || (x0 >= x1)) |
return; |
|
|
if (y0 >= y1 || x0 >= x1) return; |
screen.rgb_conv(cbuf, color); |
|
|
sp = &screen.fb_addr[FB_POS(x0, y0)]; |
dp = sp; |
|
|
/* Draw the first line. */ |
for (x = x0; x < x1; x++) { |
memcpy(dp, cbuf, screen.pixelbytes); |
dp += screen.pixelbytes; |
} |
|
|
dp = sp + screen.scanline; |
copy_bytes = (x1 - x0) * screen.pixelbytes; |
|
|
/* Draw the remaining lines by copying. */ |
for (y = y0 + 1; y < y1; y++) { |
memcpy(dp, sp, copy_bytes); |
381,15 → 329,14 |
*/ |
static void vport_redraw(viewport_t *vport) |
{ |
unsigned int col; |
unsigned int row; |
|
unsigned int row, col; |
|
for (row = 0; row < vport->rows; row++) { |
for (col = 0; col < vport->cols; col++) { |
draw_vp_glyph(vport, false, col, row); |
} |
} |
|
|
if (COL2X(vport->cols) < vport->width) { |
draw_filled_rect( |
vport->x + COL2X(vport->cols), vport->y, |
396,7 → 343,7 |
vport->x + vport->width, vport->y + vport->height, |
vport->attr.bg_color); |
} |
|
|
if (ROW2Y(vport->rows) < vport->height) { |
draw_filled_rect( |
vport->x, vport->y + ROW2Y(vport->rows), |
408,8 → 355,8 |
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, |
uint32_t bg_color) |
{ |
size_t i; |
|
unsigned i; |
|
for (i = 0; i < len; i++) { |
backbuf[i].glyph = 0; |
backbuf[i].fg_color = fg_color; |
437,36 → 384,32 |
*/ |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
unsigned int col; |
unsigned int row; |
unsigned int x; |
unsigned int y; |
uint32_t glyph; |
unsigned int row, col; |
unsigned int x, y; |
uint8_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
bb_cell_t *bbp; |
bb_cell_t *xbp; |
|
bb_cell_t *bbp, *xbp; |
|
/* |
* Redraw. |
*/ |
|
|
y = vport->y; |
for (row = 0; row < vport->rows; row++) { |
x = vport->x; |
for (col = 0; col < vport->cols; col++) { |
if (((int) row + lines >= 0) && |
((int) row + lines < (int) vport->rows)) { |
if ((row + lines >= 0) && (row + lines < vport->rows)) { |
xbp = &vport->backbuf[BB_POS(vport, col, row + lines)]; |
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
|
|
glyph = xbp->glyph; |
fg_color = xbp->fg_color; |
bg_color = xbp->bg_color; |
|
if ((bbp->glyph == glyph) |
&& (bbp->fg_color == xbp->fg_color) |
&& (bbp->bg_color == xbp->bg_color)) { |
|
if (bbp->glyph == glyph && |
bbp->fg_color == xbp->fg_color && |
bbp->bg_color == xbp->bg_color) { |
x += FONT_WIDTH; |
continue; |
} |
475,18 → 418,18 |
fg_color = vport->attr.fg_color; |
bg_color = vport->attr.bg_color; |
} |
|
(*vport->dglyph)(x, y, false, screen.glyphs, glyph, |
|
(*vport->dglyph)(x, y, false, vport->glyphs, glyph, |
fg_color, bg_color); |
x += FONT_WIDTH; |
} |
y += FONT_SCANLINES; |
} |
|
|
/* |
* Scroll backbuffer. |
*/ |
|
|
if (lines > 0) { |
memmove(vport->backbuf, vport->backbuf + vport->cols * lines, |
vport->cols * (vport->rows - lines) * sizeof(bb_cell_t)); |
505,8 → 448,10 |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
* @param vport Viewport |
* |
*/ |
static void render_glyphs(void) |
static void render_glyphs(viewport_t* vport) |
{ |
unsigned int glyph; |
|
517,16 → 462,21 |
unsigned int x; |
|
for (x = 0; x < FONT_WIDTH; x++) { |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? true : false); |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
? 0xffffff : 0x000000); |
|
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? false : true); |
screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
? 0x000000 : 0xffffff); |
} |
} |
} |
|
screen.rgb_conv(vport->bgpixel, vport->attr.bg_color); |
} |
|
|
/** Create new viewport |
* |
* @param x Origin of the viewport (x). |
546,7 → 496,6 |
if (!viewports[i].initialized) |
break; |
} |
|
if (i == MAX_VIEWPORTS) |
return ELIMIT; |
|
553,6 → 502,7 |
unsigned int cols = width / FONT_WIDTH; |
unsigned int rows = height / FONT_SCANLINES; |
unsigned int bbsize = cols * rows * sizeof(bb_cell_t); |
unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
unsigned int word_size = sizeof(unsigned long); |
|
bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize); |
559,13 → 509,21 |
if (!backbuf) |
return ENOMEM; |
|
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) { |
free(backbuf); |
return ENOMEM; |
} |
|
uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes); |
if (!bgpixel) { |
free(glyphs); |
free(backbuf); |
return ENOMEM; |
} |
|
|
backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR); |
memset(glyphs, 0, glyphsize); |
memset(bgpixel, 0, screen.pixelbytes); |
|
viewports[i].x = x; |
579,24 → 537,26 |
viewports[i].attr.bg_color = DEFAULT_BGCOLOR; |
viewports[i].attr.fg_color = DEFAULT_FGCOLOR; |
|
viewports[i].glyphs = glyphs; |
viewports[i].bgpixel = bgpixel; |
|
|
/* |
* Conditions necessary to select aligned version: |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
* Conditions necessary to select aligned version: |
* |
* - word size is divisible by pixelbytes |
* - cell scanline size is divisible by word size |
* - cell scanlines are word-aligned |
*/ |
if (((word_size % screen.pixelbytes) == 0) |
&& ((FONT_WIDTH * screen.pixelbytes) % word_size == 0) |
&& ((x * screen.pixelbytes) % word_size == 0) |
&& (screen.scanline % word_size == 0)) { |
if ((word_size % screen.pixelbytes) == 0 && |
(FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
(x * screen.pixelbytes) % word_size == 0 && |
screen.scanline % word_size == 0) { |
|
viewports[i].dglyph = draw_glyph_aligned; |
} else { |
viewports[i].dglyph = draw_glyph_fallback; |
} |
|
|
viewports[i].cur_col = 0; |
viewports[i].cur_row = 0; |
viewports[i].cursor_active = false; |
607,7 → 567,7 |
|
viewports[i].initialized = true; |
|
screen.rgb_conv(viewports[i].bgpixel, viewports[i].attr.bg_color); |
render_glyphs(&viewports[i]); |
|
return i; |
} |
627,64 → 587,41 |
{ |
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb_conv = bgr_323; |
screen.mask_conv = mask_323; |
screen.rgb_conv = rgb_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5_LE: |
screen.rgb_conv = rgb_555_le; |
screen.mask_conv = mask_555; |
case VISUAL_RGB_5_5_5: |
screen.rgb_conv = rgb_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_5_5_BE: |
screen.rgb_conv = rgb_555_be; |
screen.mask_conv = mask_555; |
case VISUAL_RGB_5_6_5: |
screen.rgb_conv = rgb_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5_LE: |
screen.rgb_conv = rgb_565_le; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5_BE: |
screen.rgb_conv = rgb_565_be; |
screen.mask_conv = mask_565; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_8_8_8: |
screen.rgb_conv = rgb_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_BGR_8_8_8: |
screen.rgb_conv = bgr_888; |
screen.mask_conv = mask_888; |
screen.pixelbytes = 3; |
break; |
case VISUAL_RGB_8_8_8_0: |
screen.rgb_conv = rgb_8880; |
screen.mask_conv = mask_8880; |
screen.rgb_conv = rgb_888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_RGB_0_8_8_8: |
screen.rgb_conv = rgb_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_0_8_8_8: |
screen.rgb_conv = bgr_0888; |
screen.mask_conv = mask_0888; |
screen.pixelbytes = 4; |
break; |
case VISUAL_BGR_8_8_8_0: |
screen.rgb_conv = bgr_8880; |
screen.mask_conv = mask_8880; |
screen.pixelbytes = 4; |
break; |
default: |
return false; |
} |
|
|
screen.fb_addr = (unsigned char *) addr; |
screen.xres = xres; |
screen.yres = yres; |
693,16 → 630,6 |
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes; |
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES; |
|
size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) |
return false; |
|
memset(glyphs, 0, glyphsize); |
screen.glyphs = glyphs; |
|
render_glyphs(); |
|
/* Create first viewport */ |
vport_create(0, 0, xres, yres); |
|
723,47 → 650,47 |
* making it very fast. Most notably this version is not applicable at 24 bits |
* per pixel. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
*/ |
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i; |
unsigned int yd; |
unsigned long fg_buf; |
unsigned long bg_buf; |
unsigned int i, yd; |
unsigned long fg_buf, bg_buf; |
unsigned long *maskp, *dp; |
unsigned long mask; |
|
unsigned int ww, d_add; |
|
/* |
* Prepare a pair of words, one filled with foreground-color |
* pattern and the other filled with background-color pattern. |
*/ |
for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
screen.rgb_conv(&((uint8_t *) &fg_buf)[i * screen.pixelbytes], |
screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes], |
fg_color); |
screen.rgb_conv(&((uint8_t *) &bg_buf)[i * screen.pixelbytes], |
screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes], |
bg_color); |
} |
|
|
|
/* Pointer to the current position in the mask. */ |
unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
|
maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
|
/* Pointer to the current position on the screen. */ |
unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
|
dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
|
/* Width of the character cell in words. */ |
unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
|
ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
|
/* Offset to add when moving to another screen scanline. */ |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
* Now process the cell scanline, combining foreground |
773,7 → 700,7 |
mask = *maskp++; |
*dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
} |
|
|
/* Move to the beginning of the next scanline of the cell. */ |
dp = (unsigned long *) ((uint8_t *) dp + d_add); |
} |
784,26 → 711,23 |
* This version does not make use of the pre-rendered mask, it uses |
* the font bitmap directly. It works always, but it is slower. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
* |
* @param x x coordinate of top-left corner on screen. |
* @param y y coordinate of top-left corner on screen. |
* @param cursor Draw glyph with cursor |
* @param glyphs Pointer to font bitmap. |
* @param glyph Code of the glyph to draw. |
* @param fg_color Foreground color. |
* @param bg_color Backgroudn color. |
*/ |
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color) |
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
{ |
unsigned int i; |
unsigned int j; |
unsigned int yd; |
uint8_t fg_buf[4]; |
uint8_t bg_buf[4]; |
uint8_t *sp; |
unsigned int i, j, yd; |
uint8_t fg_buf[4], bg_buf[4]; |
uint8_t *dp, *sp; |
unsigned int d_add; |
uint8_t b; |
|
|
/* Pre-render 1x the foreground and background color pixels. */ |
if (cursor) { |
screen.rgb_conv(fg_buf, bg_color); |
812,26 → 736,26 |
screen.rgb_conv(fg_buf, fg_color); |
screen.rgb_conv(bg_buf, bg_color); |
} |
|
|
/* Pointer to the current position on the screen. */ |
uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
|
dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
|
/* Offset to add when moving to another screen scanline. */ |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
b = fb_font[glyph][yd]; |
|
b = fb_font[glyph * FONT_SCANLINES + yd]; |
|
for (i = 0; i < FONT_WIDTH; i++) { |
/* Choose color based on the current bit. */ |
sp = (b & 0x80) ? fg_buf : bg_buf; |
|
|
/* Copy the pixel. */ |
for (j = 0; j < screen.pixelbytes; j++) { |
*dp++ = *sp++; |
} |
|
|
/* Move to the next bit. */ |
b = b << 1; |
} |
841,7 → 765,7 |
} |
} |
|
/** Draw glyph at specified position in viewport. |
/** Draw glyph at specified position in viewport. |
* |
* @param vport Viewport identification |
* @param cursor Draw glyph with cursor |
854,12 → 778,16 |
{ |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
|
uint8_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
|
uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
|
(*vport->dglyph)(x, y, cursor, screen.glyphs, glyph, |
glyph = vport->backbuf[BB_POS(vport, col, row)].glyph; |
fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color; |
bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color; |
|
(*vport->dglyph)(x, y, cursor, vport->glyphs, glyph, |
fg_color, bg_color); |
} |
|
908,20 → 836,20 |
* @param row Screen position relative to viewport |
* |
*/ |
static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row) |
static void draw_char(viewport_t *vport, uint8_t c, unsigned int col, unsigned int row) |
{ |
bb_cell_t *bbp; |
|
|
/* Do not hide cursor if we are going to overwrite it */ |
if ((vport->cursor_active) && (vport->cursor_shown) && |
((vport->cur_col != col) || (vport->cur_row != row))) |
cursor_hide(vport); |
|
|
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
bbp->glyph = fb_font_glyph(c); |
bbp->glyph = c; |
bbp->fg_color = vport->attr.fg_color; |
bbp->bg_color = vport->attr.bg_color; |
|
|
draw_vp_glyph(vport, false, col, row); |
|
vport->cur_col = col; |
938,41 → 866,35 |
cursor_show(vport); |
} |
|
/** Draw text data to viewport. |
|
/** Draw text data to viewport |
* |
* @param vport Viewport id |
* @param data Text data. |
* @param x Leftmost column of the area. |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
* @param data Text data fitting exactly into viewport |
* |
*/ |
static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
static void draw_text_data(viewport_t *vport, keyfield_t *data) |
{ |
unsigned int i; |
unsigned int j; |
bb_cell_t *bbp; |
attrs_t *a; |
attr_rgb_t rgb; |
|
for (j = 0; j < h; j++) { |
for (i = 0; i < w; i++) { |
unsigned int col = x + i; |
unsigned int row = y + j; |
|
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
|
a = &data[j * w + i].attrs; |
rgb_from_attr(&rgb, a); |
|
bbp->glyph = fb_font_glyph(data[j * w + i].character); |
bbp->fg_color = rgb.fg_color; |
bbp->bg_color = rgb.bg_color; |
|
draw_vp_glyph(vport, false, col, row); |
} |
for (i = 0; i < vport->cols * vport->rows; i++) { |
unsigned int col = i % vport->cols; |
unsigned int row = i / vport->cols; |
|
bbp = &vport->backbuf[BB_POS(vport, col, row)]; |
uint8_t glyph = bbp->glyph; |
|
a = &data[i].attrs; |
rgb_from_attr(&rgb, a); |
|
bbp->glyph = data[i].character; |
bbp->fg_color = rgb.fg_color; |
bbp->bg_color = rgb.bg_color; |
|
draw_vp_glyph(vport, false, col, row); |
} |
cursor_show(vport); |
} |
1058,8 → 980,8 |
* |
* @return false if the call was not handled byt this function, true otherwise |
* |
* Note: this function is not thread-safe, you would have |
* to redefine static variables with fibril_local. |
* Note: this function is not threads safe, you would have |
* to redefine static variables with __thread |
* |
*/ |
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp) |
1076,8 → 998,6 |
viewport_t *vport = &viewports[vp]; |
unsigned int x; |
unsigned int y; |
unsigned int w; |
unsigned int h; |
|
switch (IPC_GET_METHOD(*call)) { |
case IPC_M_SHARE_OUT: |
1085,11 → 1005,10 |
if (IPC_GET_ARG1(*call) == shm_id) { |
void *dest = as_get_mappable_page(IPC_GET_ARG2(*call)); |
shm_size = IPC_GET_ARG2(*call); |
if (ipc_answer_1(callid, EOK, (sysarg_t) dest)) { |
if (!ipc_answer_1(callid, EOK, (sysarg_t) dest)) |
shm = dest; |
else |
shm_id = 0; |
return false; |
} |
shm = dest; |
|
if (shm[0] != 'P') |
return false; |
1139,23 → 1058,15 |
IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport); |
break; |
case FB_DRAW_TEXT_DATA: |
x = IPC_GET_ARG1(*call); |
y = IPC_GET_ARG2(*call); |
w = IPC_GET_ARG3(*call); |
h = IPC_GET_ARG4(*call); |
if (!interbuffer) { |
retval = EINVAL; |
break; |
} |
if (x + w > vport->cols || y + h > vport->rows) { |
if (intersize < vport->cols * vport->rows * sizeof(*interbuffer)) { |
retval = EINVAL; |
break; |
} |
if (intersize < w * h * sizeof(*interbuffer)) { |
retval = EINVAL; |
break; |
} |
draw_text_data(vport, interbuffer, x, y, w, h); |
draw_text_data(vport, interbuffer); |
break; |
default: |
handled = false; |
1267,7 → 1178,7 |
counts = (counts + 1) % 8; |
if (counts) |
return; |
|
|
for (i = 0; i < MAX_ANIMATIONS; i++) { |
if ((!animations[i].animlen) || (!animations[i].initialized) || |
(!animations[i].enabled)) |
1584,8 → 1495,8 |
int retval; |
unsigned int i; |
int scroll; |
wchar_t ch; |
unsigned int col, row; |
uint8_t glyph; |
unsigned int row, col; |
|
if ((vport->cursor_active) || (anims_enabled)) |
callid = async_get_call_timeout(&call, 250000); |
1621,9 → 1532,9 |
return; |
|
case FB_PUTCHAR: |
ch = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
row = IPC_GET_ARG3(call); |
glyph = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
col = IPC_GET_ARG3(call); |
|
if ((col >= vport->cols) || (row >= vport->rows)) { |
retval = EINVAL; |
1631,7 → 1542,7 |
} |
ipc_answer_0(callid, EOK); |
|
draw_char(vport, ch, col, row); |
draw_char(vport, glyph, col, row); |
|
/* Message already answered */ |
continue; |
1641,8 → 1552,8 |
retval = EOK; |
break; |
case FB_CURSOR_GOTO: |
col = IPC_GET_ARG1(call); |
row = IPC_GET_ARG2(call); |
row = IPC_GET_ARG1(call); |
col = IPC_GET_ARG2(call); |
|
if ((col >= vport->cols) || (row >= vport->rows)) { |
retval = EINVAL; |
1662,11 → 1573,8 |
retval = EOK; |
break; |
case FB_GET_CSIZE: |
ipc_answer_2(callid, EOK, vport->cols, vport->rows); |
ipc_answer_2(callid, EOK, vport->rows, vport->cols); |
continue; |
case FB_GET_COLOR_CAP: |
ipc_answer_1(callid, EOK, FB_CCAP_RGB); |
continue; |
case FB_SCROLL: |
scroll = IPC_GET_ARG1(call); |
if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) { |
1711,6 → 1619,8 |
break; |
} |
viewports[i].initialized = false; |
if (viewports[i].glyphs) |
free(viewports[i].glyphs); |
if (viewports[i].bgpixel) |
free(viewports[i].bgpixel); |
if (viewports[i].backbuf) |
1737,10 → 1647,6 |
mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); |
retval = EOK; |
break; |
case FB_SCREEN_YIELD: |
case FB_SCREEN_RECLAIM: |
retval = EOK; |
break; |
default: |
retval = ENOENT; |
} |
1761,17 → 1667,17 |
unsigned int fb_height = sysinfo_value("fb.height"); |
unsigned int fb_scanline = sysinfo_value("fb.scanline"); |
unsigned int fb_visual = sysinfo_value("fb.visual"); |
|
|
unsigned int fbsize = fb_scanline * fb_height; |
void *fb_addr = as_get_mappable_page(fbsize); |
|
|
if (physmem_map(fb_ph_addr + fb_offset, fb_addr, |
ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0) |
return -1; |
|
|
if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual)) |
return 0; |
|
|
return -1; |
} |
|