Changeset dc033a1 in mainline for uspace/srv/console/console.c


Ignore:
Timestamp:
2009-03-22T17:45:15Z (15 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade
Children:
3fe00ee
Parents:
0a5116db
Message:

Get rid of FB_WRITE. We can use FB_DRAW_TEXT_DATA if we extend it just a little bit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/console/console.c

    r0a5116db rdc033a1  
    6363int prev_console = 0;
    6464
    65 /** Information about framebuffer
    66  */
     65/** Information about framebuffer */
    6766struct {
    6867        int phone;              /**< Framebuffer phone */
     
    9089                                                 * faster virtual console
    9190                                                 * switching */
    92 /** Size of fb_buf. */
    93 #define FB_BUF_SIZE 256
    94 
    95 /** Buffer for sending characters to FB driver. */
    96 static char fb_buf[FB_BUF_SIZE];
    97 
    98 /* Properties of fb_buf data. */
    99 static int fb_buf_row;          /**< Row where fb_buf data belong. */
    100 static int fb_buf_col;          /**< Column where fb_buf data start. */
    101 static int fb_console;          /**< VC to which fb_buf data belong. */
    102 int fb_bi = 0;                  /**< Number of valid chars in fb_buf. */
     91
     92/** Information on row-span yet unsent to FB driver. */
     93struct {
     94        int row;                /**< Row where the span lies. */
     95        int col;                /**< Leftmost column of the span. */
     96        int n;                  /**< Width of the span. */
     97} fb_pending;
    10398
    10499/** Size of cwrite_buf. */
     
    107102/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
    108103static char cwrite_buf[CWRITE_BUF_SIZE];
     104
     105static void fb_putchar(char c, int row, int col);
    109106
    110107
     
    176173}
    177174
    178 /** Write a character vector to FB driver via IPC. */
    179 static ssize_t fb_write(const char *buf, size_t nbyte, int row, int col)
    180 {
    181         ipcarg_t rc;
    182         ipc_call_t answer;
    183         aid_t req;
    184 
    185         async_serialize_start();
    186        
    187         req = async_send_2(fb_info.phone, FB_WRITE, row, col, &answer);
    188         rc = ipc_data_write_start(fb_info.phone, (void *) buf, nbyte);
    189 
    190         if (rc != EOK) {
    191                 async_wait_for(req, NULL);
    192                 async_serialize_end();
    193                 return (ssize_t) rc;
    194         }
    195 
    196         async_wait_for(req, &rc);
    197         async_serialize_end();
    198 
    199         if (rc == EOK)
    200                 return (ssize_t) IPC_GET_ARG1(answer);
    201         else
    202                 return -1;
    203 }
    204 
    205 /** Flush buffered characters to FB. */
    206 static void fb_buf_flush(void)
     175/** Send an area of screenbuffer to the FB driver. */
     176static void fb_update_area(connection_t *conn, int x, int y, int w, int h)
     177{
     178        int i, j;
     179        int rc;
     180        attrs_t *attrs;
     181        keyfield_t *field;
     182
     183        if (interbuffer) {
     184                for (j = 0; j < h; j++) {
     185                        for (i = 0; i < w; i++) {
     186                                interbuffer[i + j * w] =
     187                                    *get_field_at(&conn->screenbuffer,
     188                                        x + i, y + j);
     189                        }
     190                }
     191
     192                rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     193                    x, y, w, h);
     194        } else {
     195                rc = ENOTSUP;
     196        }
     197
     198        if (rc != 0) {
     199                attrs = &conn->screenbuffer.attrs;
     200
     201                for (j = 0; j < h; j++) {
     202                        for (i = 0; i < w; i++) {
     203                                field = get_field_at(&conn->screenbuffer,
     204                                    x + i, y + j);
     205                                if (!attrs_same(*attrs, field->attrs))
     206                                        set_attrs(&field->attrs);
     207                                attrs = &field->attrs;
     208
     209                                fb_putchar(field->character, y + j, x + i);
     210                        }
     211                }
     212        }
     213}
     214
     215/** Flush pending cells to FB. */
     216static void fb_pending_flush(void)
    207217{
    208218        screenbuffer_t *scr;
    209         int i;
    210 
    211         scr = &(connections[fb_console].screenbuffer);
    212 
    213         if (fb_bi > 0) {
    214                 if (fb_write(fb_buf, fb_bi, fb_buf_row, fb_buf_col) < 0) {
    215                         /* Try falling back to char-by-char. */
    216                         for (i = 0; i < fb_bi; i++) {
    217                                 async_msg_3(fb_info.phone, FB_PUTCHAR, fb_buf[i],
    218                                     fb_buf_row, fb_buf_col + i);
    219                         }
    220                 }
    221                 fb_bi = 0;
    222         }
    223 }
     219
     220        scr = &(connections[active_console].screenbuffer);
     221
     222        if (fb_pending.n > 0) {
     223                fb_update_area(&connections[active_console], fb_pending.col,
     224                    fb_pending.row, fb_pending.n, 1);
     225                fb_pending.n = 0;
     226        }
     227}
     228
     229/** Mark a character cell as changed.
     230 *
     231 * This adds the cell to the pending rowspan if possible. Otherwise
     232 * the old span is flushed first.
     233 */
     234static void cell_mark_changed(int row, int col)
     235{
     236        if (fb_pending.n != 0) {
     237                if (row != fb_pending.row ||
     238                    col != fb_pending.col + fb_pending.n) {
     239                        fb_pending_flush();
     240                }
     241        }
     242
     243        if (fb_pending.n == 0) {
     244                fb_pending.row = row;
     245                fb_pending.col = col;
     246        }
     247
     248        ++fb_pending.n;
     249}
     250
    224251
    225252/** Print a character to the active VC with buffering. */
    226 static void prtchr(char c, int row, int col)
    227 {
    228         if (fb_bi >= FB_BUF_SIZE)
    229                 fb_buf_flush();
    230 
    231         if (fb_bi == 0) {
    232                 fb_buf_row = row;
    233                 fb_buf_col = col;
    234                 fb_console = active_console;
    235         }
    236 
    237         fb_buf[fb_bi++] = c;
    238 }
    239 
    240 /** Check key and process special keys.
    241  *
    242  *
    243  */
     253static void fb_putchar(char c, int row, int col)
     254{
     255        async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
     256}
     257
     258/** Process a character from the client (TTY emulation). */
    244259static void write_char(int console, char key)
    245260{
     
    249264        switch (key) {
    250265        case '\n':
    251                 fb_buf_flush();
     266                fb_pending_flush();
    252267                flush_cursor = true;
    253268                scr->position_y++;
     
    255270                break;
    256271        case '\r':
    257                 fb_buf_flush();
    258272                break;
    259273        case '\t':
    260                 fb_buf_flush();
    261274                scr->position_x += 8;
    262275                scr->position_x -= scr->position_x % 8;
    263276                break;
    264277        case '\b':
    265                 fb_buf_flush();
    266278                if (scr->position_x == 0)
    267279                        break;
    268280                scr->position_x--;
    269281                if (console == active_console)
    270                         prtchr(' ', scr->position_y, scr->position_x);
     282                        cell_mark_changed(scr->position_y, scr->position_x);
    271283                screenbuffer_putchar(scr, ' ');
    272284                break;
    273285        default:       
    274286                if (console == active_console)
    275                         prtchr(key, scr->position_y, scr->position_x);
     287                        cell_mark_changed(scr->position_y, scr->position_x);
    276288
    277289                screenbuffer_putchar(scr, key);
     
    280292
    281293        if (scr->position_x >= scr->size_x) {
    282                 fb_buf_flush();
    283294                flush_cursor = true;
    284295                scr->position_y++;
     
    286297       
    287298        if (scr->position_y >= scr->size_y) {
     299                fb_pending_flush();
    288300                scr->position_y = scr->size_y - 1;
    289301                screenbuffer_clear_line(scr, scr->top_line);
     
    310322                return;
    311323
    312         fb_buf_flush();
     324        fb_pending_flush();
    313325
    314326        if (newcons == KERNEL_CONSOLE) {
     
    338350                curs_visibility(false);
    339351                if (interbuffer) {
    340                         for (i = 0; i < conn->screenbuffer.size_x; i++)
    341                                 for (j = 0; j < conn->screenbuffer.size_y; j++) {
     352                        for (j = 0; j < conn->screenbuffer.size_y; j++) {
     353                                for (i = 0; i < conn->screenbuffer.size_x; i++) {
    342354                                        unsigned int size_x;
    343355                                       
    344356                                        size_x = conn->screenbuffer.size_x;
    345                                         interbuffer[i + j * size_x] =
     357                                        interbuffer[j * size_x + i] =
    346358                                            *get_field_at(&conn->screenbuffer, i, j);
    347359                                }
     360                        }
    348361                        /* This call can preempt, but we are already at the end */
    349                         rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA);
     362                        rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
     363                            0, 0, conn->screenbuffer.size_x,
     364                            conn->screenbuffer.size_y);
    350365                }
    351366               
     
    366381                                                continue;
    367382
    368                                         prtchr(field->character, j, i);
     383                                        fb_putchar(field->character, j, i);
    369384                                }
    370385                }
     
    479494        ipcarg_t arg1, arg2, arg3, arg4;
    480495        connection_t *conn;
     496        screenbuffer_t *scr;
    481497       
    482498        if ((consnum = find_free_connection()) == -1) {
     
    535551                        break;
    536552                case CONSOLE_GOTO:
    537                         fb_buf_flush();
    538553                        screenbuffer_goto(&conn->screenbuffer,
    539554                            IPC_GET_ARG2(call), IPC_GET_ARG1(call));
     
    547562                        break;
    548563                case CONSOLE_FLUSH:
    549                         fb_buf_flush();
    550                         if (consnum == active_console)
     564                        fb_pending_flush();
     565                        if (consnum == active_console) {
    551566                                async_req_0_0(fb_info.phone, FB_FLUSH);
     567
     568                                scr = &(connections[consnum].screenbuffer);
     569                                curs_goto(scr->position_y, scr->position_x);
     570                        }
    552571                        break;
    553572                case CONSOLE_SET_STYLE:
    554                         fb_buf_flush();
     573                        fb_pending_flush();
    555574                        arg1 = IPC_GET_ARG1(call);
    556575                        screenbuffer_set_style(&conn->screenbuffer, arg1);
     
    559578                        break;
    560579                case CONSOLE_SET_COLOR:
    561                         fb_buf_flush();
     580                        fb_pending_flush();
    562581                        arg1 = IPC_GET_ARG1(call);
    563582                        arg2 = IPC_GET_ARG2(call);
     
    569588                        break;
    570589                case CONSOLE_SET_RGB_COLOR:
    571                         fb_buf_flush();
     590                        fb_pending_flush();
    572591                        arg1 = IPC_GET_ARG1(call);
    573592                        arg2 = IPC_GET_ARG2(call);
     
    578597                        break;
    579598                case CONSOLE_CURSOR_VISIBILITY:
    580                         fb_buf_flush();
     599                        fb_pending_flush();
    581600                        arg1 = IPC_GET_ARG1(call);
    582601                        conn->screenbuffer.is_cursor_visible = arg1;
     
    684703        interbuffer = as_get_mappable_page(ib_size);
    685704
     705        fb_pending.n = 0;
     706
    686707        if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
    687708            AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
Note: See TracChangeset for help on using the changeset viewer.