78,6 → 78,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); |
98,6 → 101,7 |
uint8_t *glyphs; |
|
rgb_conv_t rgb_conv; |
mask_conv_t mask_conv; |
} screen; |
|
/** Backbuffer character cell. */ |
226,10 → 230,15 |
*/ |
static void rgb_0888(void *dst, uint32_t rgb) |
{ |
*((uint32_t *) dst) = rgb & 0xffffff; |
*((uint32_t *) dst) = rgb & 0x00ffffff; |
} |
|
static void mask_0888(void *dst, bool mask) |
{ |
*((uint32_t *) dst) = (mask ? 0x00ffffff : 0); |
} |
|
|
/** ABGR 8:8:8:8 conversion |
* |
*/ |
250,7 → 259,20 |
((uint8_t *) dst)[2] = RED(rgb, 8); |
} |
|
static void mask_888(void *dst, bool mask) |
{ |
if (mask) { |
((uint8_t *) dst)[0] = 0xff; |
((uint8_t *) dst)[1] = 0xff; |
((uint8_t *) dst)[2] = 0xff; |
} else { |
((uint8_t *) dst)[0] = 0; |
((uint8_t *) dst)[1] = 0; |
((uint8_t *) dst)[2] = 0; |
} |
} |
|
|
/** BGR 8:8:8 conversion |
* |
*/ |
271,7 → 293,12 |
= (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5); |
} |
|
static void mask_555(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0x7fff : 0); |
} |
|
|
/** RGB 5:6:5 conversion |
* |
*/ |
281,7 → 308,12 |
= (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5); |
} |
|
static void mask_565(void *dst, bool mask) |
{ |
*((uint16_t *) dst) = (mask ? 0xffff : 0); |
} |
|
|
/** RGB 3:2:3 |
* |
*/ |
291,20 → 323,30 |
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); |
} |
|
static void mask_323(void *dst, bool mask) |
{ |
*((uint8_t *) dst) = (mask ? 0xff : 0); |
} |
|
/** 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, y; |
unsigned int x; |
unsigned int y; |
unsigned int copy_bytes; |
|
uint8_t *sp, *dp; |
uint8_t *sp; |
uint8_t *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)]; |
333,7 → 375,8 |
*/ |
static void vport_redraw(viewport_t *vport) |
{ |
unsigned int row, col; |
unsigned int row; |
unsigned int col; |
|
for (row = 0; row < vport->rows; row++) { |
for (col = 0; col < vport->cols; col++) { |
359,7 → 402,7 |
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, |
uint32_t bg_color) |
{ |
unsigned i; |
size_t i; |
|
for (i = 0; i < len; i++) { |
backbuf[i].glyph = 0; |
388,12 → 431,15 |
*/ |
static void vport_scroll(viewport_t *vport, int lines) |
{ |
unsigned int row, col; |
unsigned int x, y; |
unsigned int row; |
unsigned int col; |
unsigned int x; |
unsigned int y; |
uint32_t glyph; |
uint32_t fg_color; |
uint32_t bg_color; |
bb_cell_t *bbp, *xbp; |
bb_cell_t *bbp; |
bb_cell_t *xbp; |
|
/* |
* Redraw. |
411,9 → 457,9 |
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; |
} |
451,6 → 497,7 |
* |
* Convert glyphs from device independent font |
* description to current visual representation. |
* |
*/ |
static void render_glyphs(void) |
{ |
463,19 → 510,16 |
unsigned int x; |
|
for (x = 0; x < FONT_WIDTH; x++) { |
screen.rgb_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) |
? 0xffffff : 0x000000); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? 1 : 0); |
|
screen.rgb_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) |
? 0x000000 : 0xffffff); |
screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
(fb_font[glyph][y] & (1 << (7 - x))) ? 1 : 0); |
} |
} |
} |
} |
|
|
/** Create new viewport |
* |
* @param x Origin of the viewport (x). |
495,6 → 539,7 |
if (!viewports[i].initialized) |
break; |
} |
|
if (i == MAX_VIEWPORTS) |
return ELIMIT; |
|
531,16 → 576,15 |
|
/* |
* 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; |
574,39 → 618,47 |
static bool screen_init(void *addr, unsigned int xres, unsigned int yres, |
unsigned int scan, unsigned int visual) |
{ |
unsigned int glyphsize; |
uint8_t *glyphs; |
|
|
switch (visual) { |
case VISUAL_INDIRECT_8: |
screen.rgb_conv = rgb_323; |
screen.mask_conv = mask_323; |
screen.pixelbytes = 1; |
break; |
case VISUAL_RGB_5_5_5: |
screen.rgb_conv = rgb_555; |
screen.mask_conv = mask_555; |
screen.pixelbytes = 2; |
break; |
case VISUAL_RGB_5_6_5: |
screen.rgb_conv = rgb_565; |
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_888; |
screen.mask_conv = mask_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; |
default: |
621,8 → 673,8 |
screen.glyphscanline = FONT_WIDTH * screen.pixelbytes; |
screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES; |
|
glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
glyphs = (uint8_t *) malloc(glyphsize); |
size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
uint8_t *glyphs = (uint8_t *) malloc(glyphsize); |
if (!glyphs) |
return false; |
|
658,15 → 710,16 |
* @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) |
{ |
unsigned int i, yd; |
unsigned long fg_buf, bg_buf; |
unsigned long *maskp, *dp; |
unsigned int i; |
unsigned int yd; |
unsigned long fg_buf; |
unsigned long bg_buf; |
unsigned long mask; |
unsigned int ww, d_add; |
|
/* |
* Prepare a pair of words, one filled with foreground-color |
680,16 → 733,16 |
} |
|
/* Pointer to the current position in the mask. */ |
maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
|
/* Pointer to the current position on the screen. */ |
dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
|
/* Width of the character cell in words. */ |
ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
|
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* |
718,14 → 771,17 |
* @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) |
{ |
unsigned int i, j, yd; |
uint8_t fg_buf[4], bg_buf[4]; |
uint8_t *dp, *sp; |
unsigned int d_add; |
unsigned int i; |
unsigned int j; |
unsigned int yd; |
uint8_t fg_buf[4]; |
uint8_t bg_buf[4]; |
uint8_t *sp; |
uint8_t b; |
|
/* Pre-render 1x the foreground and background color pixels. */ |
738,10 → 794,10 |
} |
|
/* Pointer to the current position on the screen. */ |
dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
|
/* Offset to add when moving to another screen scanline. */ |
d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
for (yd = 0; yd < FONT_SCANLINES; yd++) { |
/* Byte containing bits of the glyph scanline. */ |
779,14 → 835,10 |
unsigned int x = vport->x + COL2X(col); |
unsigned int y = vport->y + ROW2Y(row); |
|
uint32_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; |
|
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, screen.glyphs, glyph, |
fg_color, bg_color); |
} |
874,11 → 926,13 |
* @param y Topmost row of the area. |
* @param w Number of rows. |
* @param h Number of columns. |
* |
*/ |
static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x, |
unsigned int y, unsigned int w, unsigned int h) |
{ |
unsigned int i, j; |
unsigned int i; |
unsigned int j; |
bb_cell_t *bbp; |
attrs_t *a; |
attr_rgb_t rgb; |