Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1551 → Rev 1552

/uspace/trunk/console/gcons.h
32,5 → 32,6
void gcons_init(int phone);
void gcons_change_console(int consnum);
void gcons_notify_char(int consnum);
void gcons_in_kernel(void);
 
#endif
/uspace/trunk/console/screenbuffer.h
30,8 → 30,8
#define __SCREENBUFFER_H__
 
 
#define DEFAULT_FOREGROUND_COLOR 0xffffff /**< default console foreground color */
#define DEFAULT_BACKGROUND_COLOR 0x00003f /**< default console background color */
#define DEFAULT_FOREGROUND 0xffff00 /**< default console foreground color */
#define DEFAULT_BACKGROUND 0x000080 /**< default console background color */
 
typedef struct {
unsigned int bg_color; /**< background color */
/uspace/trunk/console/console.c
69,10 → 69,12
screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen contents and related settings. */
} connection_t;
 
connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual consoles */
keyfield_t *interbuffer = NULL; /**< Pointer to memory shared with framebufer used for faster virt. console switching */
static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual consoles */
static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared with framebufer used for faster virt. console switching */
 
static int kernel_pixmap = -1; /**< Number of fb pixmap, where kernel console is stored */
 
 
/** Find unused virtual console.
*
*/
103,6 → 105,38
return CONSOLE_COUNT;
}
 
static void clrscr(void)
{
nsend_call(fb_info.phone, FB_CLEAR, 0);
}
 
static void curs_visibility(int v)
{
send_call(fb_info.phone, FB_CURSOR_VISIBILITY, v);
}
 
static void curs_goto(int row, int col)
{
nsend_call_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
}
 
static void set_style(style_t *style)
{
nsend_call_2(fb_info.phone, FB_SET_STYLE, style->fg_color, style->bg_color);
}
 
static void set_style_col(int fgcolor, int bgcolor)
{
nsend_call_2(fb_info.phone, FB_SET_STYLE, fgcolor, bgcolor);
}
 
static void prtchr(char c, int row, int col)
{
nsend_call_3(fb_info.phone, FB_PUTCHAR, c, row, col);
}
 
/** Check key and process special keys.
*
* */
127,17 → 161,15
 
scr->position_x--;
 
if (console == active_console) {
nsend_call_3(fb_info.phone, FB_PUTCHAR, ' ', scr->position_y, scr->position_x);
}
if (console == active_console)
prtchr(' ', scr->position_y, scr->position_x);
screenbuffer_putchar(scr, ' ');
break;
default:
if (console == active_console) {
nsend_call_3(fb_info.phone, FB_PUTCHAR, key, scr->position_y, scr->position_x);
}
if (console == active_console)
prtchr(key, scr->position_y, scr->position_x);
screenbuffer_putchar(scr, key);
scr->position_x++;
154,12 → 186,98
scr->position_x = scr->position_x % scr->size_x;
if (console == active_console)
send_call_2(fb_info.phone, FB_CURSOR_GOTO, scr->position_y, scr->position_x);
if (console == active_console)
curs_goto(scr->position_y, scr->position_x);
}
 
/** Save current screen to pixmap, draw old pixmap
*
* @param oldpixmap Old pixmap
* @return ID of pixmap of current screen
*/
static int switch_screens(int oldpixmap)
{
int newpmap;
/* Save screen */
newpmap = sync_send(fb_info.phone, FB_VP2PIXMAP, 0, NULL);
if (newpmap < 0)
return -1;
 
if (oldpixmap != -1) {
/* Show old screen */
nsend_call_2(fb_info.phone, FB_VP_DRAW_PIXMAP, 0, oldpixmap);
/* Drop old pixmap */
nsend_call(fb_info.phone, FB_DROP_PIXMAP, oldpixmap);
}
return newpmap;
}
 
/** Switch to new console */
static void change_console(int newcons)
{
connection_t *conn;
static int console_pixmap = -1;
int i, j;
char c;
 
if (newcons == active_console)
return;
 
if (newcons == -1) {
if (active_console == -1)
return;
active_console = -1;
curs_visibility(0);
 
if (kernel_pixmap == -1) {
/* store/restore unsupported */
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
clrscr();
} else {
gcons_in_kernel();
console_pixmap = switch_screens(kernel_pixmap);
kernel_pixmap = -1;
}
 
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
return;
}
if (console_pixmap != -1) {
kernel_pixmap = switch_screens(console_pixmap);
console_pixmap = -1;
}
active_console = newcons;
gcons_change_console(newcons);
conn = &connections[active_console];
 
curs_visibility(0);
if (interbuffer) {
for (i = 0; i < conn->screenbuffer.size_x; i++)
for (j = 0; j < conn->screenbuffer.size_y; j++)
interbuffer[i + j*conn->screenbuffer.size_x] = *get_field_at(&(conn->screenbuffer),i, j);
sync_send_2(fb_info.phone, FB_DRAW_TEXT_DATA, 0, 0, NULL, NULL);
} else {
clrscr();
for (i = 0; i < conn->screenbuffer.size_x; i++)
for (j = 0; j < conn->screenbuffer.size_y; j++) {
c = get_field_at(&(conn->screenbuffer),i, j)->character;
if (c && c != ' ')
prtchr(c, j, i);
}
}
curs_goto(conn->screenbuffer.position_y, conn->screenbuffer.position_x);
set_style(&conn->screenbuffer.style);
curs_visibility(1);
}
 
/** Handler for keyboard */
static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
{
166,8 → 284,7
ipc_callid_t callid;
ipc_call_t call;
int retval;
int i, j;
char c,d;
char c;
connection_t *conn;
/* Ignore parameters, the connection is alread opened */
188,51 → 305,10
conn = &connections[active_console];
// if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + CONSOLE_COUNT)) {
if ((c >= '0') && (c < '0' + CONSOLE_COUNT)) {
if (c == '0') {
/* switch to kernel console*/
nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0);
nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR);
nsend_call(fb_info.phone, FB_CLEAR, 0);
/* FIXME: restore kernel console */
__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
break;
} else {
c = c - '1';
if (c == active_console)
break;
active_console = c;
gcons_change_console(c);
}
conn = &connections[active_console];
 
nsend_call(fb_info.phone, FB_CURSOR_VISIBILITY, 0);
if (interbuffer) {
for (i = 0; i < conn->screenbuffer.size_x; i++)
for (j = 0; j < conn->screenbuffer.size_y; j++)
interbuffer[i + j*conn->screenbuffer.size_x] = *get_field_at(&(conn->screenbuffer),i, j);
sync_send_2(fb_info.phone, FB_DRAW_TEXT_DATA, 0, 0, NULL, NULL);
} else {
nsend_call(fb_info.phone, FB_CLEAR, 0);
for (i = 0; i < conn->screenbuffer.size_x; i++)
for (j = 0; j < conn->screenbuffer.size_y; j++) {
d = get_field_at(&(conn->screenbuffer),i, j)->character;
if (d && d != ' ')
nsend_call_3(fb_info.phone, FB_PUTCHAR, d, j, i);
}
 
}
nsend_call_2(fb_info.phone, FB_CURSOR_GOTO, conn->screenbuffer.position_y, conn->screenbuffer.position_x);
nsend_call_2(fb_info.phone, FB_SET_STYLE, conn->screenbuffer.style.fg_color, \
conn->screenbuffer.style.bg_color);
send_call(fb_info.phone, FB_CURSOR_VISIBILITY, 1);
 
if (c == '0')
change_console(-1);
else
change_console(c - '1');
break;
}
314,7 → 390,7
arg2 = IPC_GET_ARG2(call);
screenbuffer_set_style(&(connections[consnum].screenbuffer),arg1, arg2);
if (consnum == active_console)
nsend_call_2(fb_info.phone, FB_SET_STYLE, arg1, arg2);
set_style_col(arg1, arg2);
break;
case CONSOLE_GETCHAR:
361,6 → 437,9
while ((fb_info.phone = ipc_connect_me_to(PHONE_NS, SERVICE_VIDEO, 0)) < 0) {
usleep(10000);
}
/* Save old kernel screen */
kernel_pixmap = switch_screens(-1);
 
/* Initialize gcons */
gcons_init(fb_info.phone);
369,8 → 448,8
 
ipc_call_sync_2(fb_info.phone, FB_GET_CSIZE, 0, 0, &(fb_info.rows), &(fb_info.cols));
nsend_call_2(fb_info.phone, FB_SET_STYLE, DEFAULT_FOREGROUND_COLOR, DEFAULT_BACKGROUND_COLOR);
nsend_call(fb_info.phone, FB_CLEAR, 0);
set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
clrscr();
/* Init virtual consoles */
for (i = 0; i < CONSOLE_COUNT; i++) {
394,8 → 473,6
}
}
 
/* FIXME: save kernel console screen */
async_new_connection(phonehash, 0, NULL, keyboard_events);
sync_send_2(fb_info.phone, FB_CURSOR_GOTO, 0, 0, NULL, NULL);
/uspace/trunk/console/gcons.c
125,8 → 125,9
{
if (!use_gcons)
return;
draw_stat(active_console, CONS_IDLE);
 
if (active_console != -1)
draw_stat(active_console, CONS_IDLE);
active_console = consnum;
draw_stat(consnum, CONS_ACTIVE);
console_has_input[consnum] = 0;
134,6 → 135,7
vp_switch(console_vp);
}
 
/** Notification function that gets called on new output to virtual console */
void gcons_notify_char(int consnum)
{
if (!use_gcons)
143,11 → 145,31
return;
 
console_has_input[consnum] = 1;
 
if (active_console == -1)
return;
 
draw_stat(consnum, CONS_HAS_INPUT);
vp_switch(console_vp);
 
}
 
/** Change to kernel console */
void gcons_in_kernel(void)
{
draw_stat(active_console, CONS_IDLE);
active_console = -1; /* Set to kernel console */
vp_switch(0);
}
 
/** Draw a PPM pixmap to framebuffer
*
* @param logo Pointer to PPM data
* @param size Size of PPM data
* @param x Coordinate of upper left corner
* @param y Coordinate of upper left corner
*/
static void draw_pixmap(char *logo, size_t size, int x, int y)
{
char *shm;
/uspace/trunk/fb/fb.c
83,6 → 83,18
int cursor_shown;
} viewport_t;
 
/** Maximum number of saved pixmaps
* Pixmap is a saved rectangle
*/
#define MAX_PIXMAPS 256
typedef struct {
unsigned int width;
unsigned int height;
void *data;
} pixmap_t;
static pixmap_t pixmaps[MAX_PIXMAPS];
 
/* Viewport is a rectangular area on the screen */
#define MAX_VIEWPORTS 128
static viewport_t viewports[128];
 
286,24 → 298,6
invert_pixel(vp, col * COL_WIDTH + x, row * FONT_SCANLINES + y);
}
 
static void draw_logo(int vp,unsigned int startx, unsigned int starty)
{
unsigned int x;
unsigned int y;
unsigned int byte;
unsigned int rowbytes;
 
rowbytes = (helenos_width - 1) / 8 + 1;
 
for (y = 0; y < helenos_height; y++)
for (x = 0; x < helenos_width; x++) {
byte = helenos_bits[rowbytes * y + x / 8];
byte >>= x % 8;
if (byte & 1)
putpixel(vp ,startx + x, starty + y, viewports[vp].style.fg_color);
}
}
 
/***************************************************************/
/* Stdout specific functions */
 
395,6 → 389,7
viewport_create(0,0,xres,yres);
}
 
/** Hide cursor if it is shown */
static void cursor_hide(int vp)
{
viewport_t *vport = &viewports[vp];
405,6 → 400,7
}
}
 
/** Show cursor if cursor showing is enabled */
static void cursor_print(int vp)
{
viewport_t *vport = &viewports[vp];
416,6 → 412,7
}
}
 
/** Invert cursor, if it is enabled */
static void cursor_blink(int vp)
{
viewport_t *vport = &viewports[vp];
457,6 → 454,11
cursor_print(vp);
}
 
/** Draw text data to viewport
*
* @param vp Viewport id
* @param data Text data fitting exactly into viewport
*/
static void draw_text_data(int vp, keyfield_t *data)
{
viewport_t *vport = &viewports[vp];
475,6 → 477,26
cursor_print(vp);
}
 
/** Handle shared memory communication calls
*
* Protocol for drawing pixmaps:
* - FB_PREPARE_SHM(client shm identification)
* - IPC_M_SEND_AS_AREA
* - FB_DRAW_PPM(startx,starty)
* - FB_DROP_SHM
*
* Protocol for text drawing
* - IPC_M_SEND_AS_AREA
* - FB_DRAW_TEXT_DATA
*
* @param callid Callid of the current call
* @param call Current call data
* @param vp Active viewport
* @return 0 if the call was not handled byt this function, 1 otherwise
*
* note: this function is not threads safe, you would have
* to redefine static variables with __thread
*/
static int shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
{
static keyfield_t *interbuffer = NULL;
558,6 → 580,124
return handled;
}
 
/** Return first free pixmap */
static int find_free_pixmap(void)
{
int i;
for (i=0;i < MAX_PIXMAPS;i++)
if (!pixmaps[i].data)
return i;
return -1;
}
 
/** Save viewport to pixmap */
static int save_vp_to_pixmap(int vp)
{
int pm;
pixmap_t *pmap;
viewport_t *vport = &viewports[vp];
int x,y;
int rowsize;
int tmp;
 
pm = find_free_pixmap();
if (pm == -1)
return ELIMIT;
pmap = &pixmaps[pm];
pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
if (!pmap->data)
return ENOMEM;
 
pmap->width = vport->width;
pmap->height = vport->height;
rowsize = vport->width * screen.pixelbytes;
for (y=0;y < vport->height; y++) {
tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
memcpy(pmap->data + rowsize*y, screen.fbaddress + tmp, rowsize);
}
return pm;
}
 
/** Draw pixmap on screen
*
* @param vp Viewport to draw on
* @param pm Pixmap identifier
*/
static int draw_pixmap(int vp, int pm)
{
pixmap_t *pmap = &pixmaps[pm];
viewport_t *vport = &viewports[vp];
int x,y;
int tmp, srcrowsize;
int realwidth, realheight, realrowsize;
 
if (!pmap->data)
return EINVAL;
 
realwidth = pmap->width <= vport->width ? pmap->width : vport->width;
realheight = pmap->height <= vport->height ? pmap->height : vport->height;
 
srcrowsize = vport->width * screen.pixelbytes;
realrowsize = realwidth * screen.pixelbytes;
 
for (y=0; y < realheight; y++) {
tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize, realrowsize);
}
}
 
/** Handler for messages concerning pixmap handling */
static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
{
int handled = 1;
int retval = 0;
int i,nvp;
 
switch (IPC_GET_METHOD(*call)) {
case FB_VP_DRAW_PIXMAP:
nvp = IPC_GET_ARG1(*call);
if (nvp == -1)
nvp = vp;
if (nvp < 0 || nvp >= MAX_VIEWPORTS || !viewports[nvp].initialized) {
retval = EINVAL;
break;
}
i = IPC_GET_ARG2(*call);
retval = draw_pixmap(nvp, i);
break;
case FB_VP2PIXMAP:
nvp = IPC_GET_ARG1(*call);
if (nvp == -1)
nvp = vp;
if (nvp < 0 || nvp >= MAX_VIEWPORTS || !viewports[nvp].initialized)
retval = EINVAL;
else
retval = save_vp_to_pixmap(nvp);
break;
case FB_DROP_PIXMAP:
i = IPC_GET_ARG1(*call);
if (i >= MAX_PIXMAPS) {
retval = EINVAL;
break;
}
if (pixmaps[i].data) {
free(pixmaps[i].data);
pixmaps[i].data = NULL;
}
break;
default:
handled = 0;
}
 
if (handled)
ipc_answer_fast(callid, retval, 0, 0);
return handled;
}
 
/** Function for handling connections to FB
*
*/
588,6 → 728,8
}
if (shm_handle(callid, &call, vp))
continue;
if (pixmap_handle(callid, &call, vp))
continue;
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
/uspace/trunk/libc/include/async.h
70,6 → 70,8
*r2 = IPC_GET_ARG2(result);
return rc;
}
#define sync_send(phoneid, method, arg1, r1) sync_send_2(phoneid, method, arg1, 0, r1, 0)
 
static inline ipcarg_t sync_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *r1,
ipcarg_t *r2, ipcarg_t *r3)
/uspace/trunk/libc/include/ipc/fb.h
23,5 → 23,10
#define FB_DRAW_PPM 1038
#define FB_PREPARE_SHM 1039
#define FB_DROP_SHM 1040
#define FB_SHM2PIXMAP 1041
 
#define FB_VP_DRAW_PIXMAP 1042
#define FB_VP2PIXMAP 1043
#define FB_DROP_PIXMAP 1044
 
#endif