Subversion Repositories HelenOS

Compare Revisions

Regard whitespace Rev 4347 → Rev 4348

/branches/dynload/uspace/srv/fb/fb.c
68,6 → 68,8
#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 */
76,9 → 78,12
/** 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, uint8_t glyph, uint32_t fg_color, uint32_t bg_color);
uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
 
struct {
uint8_t *fb_addr;
92,12 → 97,16
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 {
uint8_t glyph;
uint32_t glyph;
uint32_t fg_color;
uint32_t bg_color;
} bb_cell_t;
120,14 → 129,13
/** 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. */
/**
* Glyph drawing function for this viewport. Different viewports
* might use different drawing functions depending on whether their
* scanlines are aligned on a word boundary.
*/
dg_t dglyph;
/* Auto-cursor position */
194,9 → 202,9
ipcarg_t bg_color, ipcarg_t attr);
 
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color);
uint8_t *glyphs, uint32_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, uint8_t glyph, uint32_t fg_color, uint32_t bg_color);
uint8_t *glyphs, uint32_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);
222,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
*
*/
246,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
*
*/
267,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
*
*/
277,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
*
*/
287,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)];
329,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++) {
355,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;
384,12 → 431,15
*/
static void vport_scroll(viewport_t *vport, int lines)
{
unsigned int row, col;
unsigned int x, y;
uint8_t glyph;
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.
407,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;
}
419,7 → 469,7
bg_color = vport->attr.bg_color;
}
 
(*vport->dglyph)(x, y, false, vport->glyphs, glyph,
(*vport->dglyph)(x, y, false, screen.glyphs, glyph,
fg_color, bg_color);
x += FONT_WIDTH;
}
448,10 → 498,8
* Convert glyphs from device independent font
* description to current visual representation.
*
* @param vport Viewport
*
*/
static void render_glyphs(viewport_t* vport)
static void render_glyphs(void)
{
unsigned int glyph;
462,21 → 510,16
unsigned int x;
for (x = 0; x < FONT_WIDTH; x++) {
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, false) + x * screen.pixelbytes],
(fb_font[glyph][y] & (1 << (7 - x))) ? true : false);
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.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->bgpixel, vport->attr.bg_color);
}
 
 
/** Create new viewport
*
* @param x Origin of the viewport (x).
496,6 → 539,7
if (!viewports[i].initialized)
break;
}
if (i == MAX_VIEWPORTS)
return ELIMIT;
502,7 → 546,6
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);
509,21 → 552,13
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;
537,21 → 572,19
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
*
*/
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;
567,7 → 600,7
viewports[i].initialized = true;
render_glyphs(&viewports[i]);
screen.rgb_conv(viewports[i].bgpixel, viewports[i].attr.bg_color);
return i;
}
585,37 → 618,47
static bool screen_init(void *addr, unsigned int xres, unsigned int yres,
unsigned int scan, unsigned int visual)
{
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:
630,6 → 673,16
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);
657,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, uint8_t glyph, uint32_t fg_color, uint32_t bg_color)
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
678,18 → 732,17
bg_color);
}
 
 
/* 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, uint8_t glyph, uint32_t fg_color, uint32_t bg_color)
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,14 → 794,14
}
 
/* 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. */
b = fb_font[glyph * FONT_SCANLINES + yd];
b = fb_font[glyph][yd];
 
for (i = 0; i < FONT_WIDTH; i++) {
/* Choose color based on the current bit. */
779,15 → 835,11
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;
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,
(*vport->dglyph)(x, y, cursor, screen.glyphs, glyph,
fg_color, bg_color);
}
 
836,7 → 888,7
* @param row Screen position relative to viewport
*
*/
static void draw_char(viewport_t *vport, uint8_t c, unsigned int col, unsigned int row)
static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row)
{
bb_cell_t *bbp;
 
846,7 → 898,7
cursor_hide(vport);
 
bbp = &vport->backbuf[BB_POS(vport, col, row)];
bbp->glyph = c;
bbp->glyph = fb_font_glyph(c);
bbp->fg_color = vport->attr.fg_color;
bbp->bg_color = vport->attr.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;
889,12 → 943,11
unsigned int row = y + j;
 
bbp = &vport->backbuf[BB_POS(vport, col, row)];
uint8_t glyph = bbp->glyph;
 
a = &data[j * w + i].attrs;
rgb_from_attr(&rgb, a);
 
bbp->glyph = data[j * w + i].character;
bbp->glyph = fb_font_glyph(data[j * w + i].character);
bbp->fg_color = rgb.fg_color;
bbp->bg_color = rgb.bg_color;
 
1510,7 → 1563,7
int retval;
unsigned int i;
int scroll;
uint8_t glyph;
wchar_t ch;
unsigned int row, col;
if ((vport->cursor_active) || (anims_enabled))
1547,7 → 1600,7
return;
case FB_PUTCHAR:
glyph = IPC_GET_ARG1(call);
ch = IPC_GET_ARG1(call);
row = IPC_GET_ARG2(call);
col = IPC_GET_ARG3(call);
1557,7 → 1610,7
}
ipc_answer_0(callid, EOK);
draw_char(vport, glyph, col, row);
draw_char(vport, ch, col, row);
/* Message already answered */
continue;
1634,8 → 1687,6
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)
1662,6 → 1713,10
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;
}