Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 68a552f in mainline


Ignore:
Timestamp:
2021-02-22T19:52:08Z (10 days ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
26853ebc
Parents:
2ab8ab3
Message:

Efficient way of rendering to the console via shared buffer

Makes congfx reasonably fast

Location:
uspace
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/terminal/terminal.c

    r2ab8ab3 r68a552f  
    3737#include <adt/list.h>
    3838#include <adt/prodcons.h>
     39#include <as.h>
    3940#include <errno.h>
    4041#include <fbfont/font-8x16.h>
     
    4950#include <task.h>
    5051#include <stdarg.h>
     52#include <stdio.h>
    5153#include <stdlib.h>
    5254#include <str.h>
     
    8688static void term_set_cursor_visibility(con_srv_t *, bool);
    8789static errno_t term_get_event(con_srv_t *, cons_event_t *);
     90static errno_t term_map(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
     91static void term_unmap(con_srv_t *);
     92static void term_buf_update(con_srv_t *, sysarg_t, sysarg_t, sysarg_t,
     93    sysarg_t);
    8894
    8995static con_ops_t con_ops = {
     
    102108        .set_rgb_color = term_set_rgb_color,
    103109        .set_cursor_visibility = term_set_cursor_visibility,
    104         .get_event = term_get_event
     110        .get_event = term_get_event,
     111        .map = term_map,
     112        .unmap = term_unmap,
     113        .update = term_buf_update
    105114};
    106115
     
    344353                                charfield_t *back_field =
    345354                                    chargrid_charfield_at(term->backbuf, x, y);
    346                                 bool update = false;
     355                                bool cupdate = false;
    347356
    348357                                if ((front_field->flags & CHAR_FLAG_DIRTY) ==
     
    350359                                        if (front_field->ch != back_field->ch) {
    351360                                                back_field->ch = front_field->ch;
    352                                                 update = true;
     361                                                cupdate = true;
    353362                                        }
    354363
     
    356365                                            back_field->attrs)) {
    357366                                                back_field->attrs = front_field->attrs;
    358                                                 update = true;
     367                                                cupdate = true;
    359368                                        }
    360369
     
    362371                                }
    363372
    364                                 if (update) {
     373                                if (cupdate) {
    365374                                        term_update_char(term, &pixelmap, sx, sy, x, y);
    366375                                        update = true;
     
    645654}
    646655
     656/** Create shared buffer for efficient rendering.
     657 *
     658 * @param srv Console server
     659 * @param cols Number of columns in buffer
     660 * @param rows Number of rows in buffer
     661 * @param rbuf Place to store pointer to new sharable buffer
     662 *
     663 * @return EOK on sucess or an error code
     664 */
     665static errno_t term_map(con_srv_t *srv, sysarg_t cols, sysarg_t rows,
     666    charfield_t **rbuf)
     667{
     668        terminal_t *term = srv_to_terminal(srv);
     669        void *buf;
     670
     671        fibril_mutex_lock(&term->mtx);
     672
     673        if (term->ubuf != NULL) {
     674                fibril_mutex_unlock(&term->mtx);
     675                return EBUSY;
     676        }
     677
     678        buf = as_area_create(AS_AREA_ANY, cols * rows * sizeof(charfield_t),
     679            AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, AS_AREA_UNPAGED);
     680        if (buf == AS_MAP_FAILED) {
     681                fibril_mutex_unlock(&term->mtx);
     682                return ENOMEM;
     683        }
     684
     685        term->ucols = cols;
     686        term->urows = rows;
     687        term->ubuf = buf;
     688        fibril_mutex_unlock(&term->mtx);
     689
     690        *rbuf = buf;
     691        return EOK;
     692}
     693
     694/** Delete shared buffer.
     695 *
     696 * @param srv Console server
     697 */
     698static void term_unmap(con_srv_t *srv)
     699{
     700        terminal_t *term = srv_to_terminal(srv);
     701        void *buf;
     702
     703        fibril_mutex_lock(&term->mtx);
     704
     705        buf = term->ubuf;
     706        term->ubuf = NULL;
     707
     708        if (buf != NULL)
     709                as_area_destroy(buf);
     710
     711        fibril_mutex_unlock(&term->mtx);
     712}
     713
     714/** Update area of terminal from shared buffer.
     715 *
     716 * @param srv Console server
     717 * @param c0 Column coordinate of top-left corner (inclusive)
     718 * @param r0 Row coordinate of top-left corner (inclusive)
     719 * @param c1 Column coordinate of bottom-right corner (exclusive)
     720 * @param r1 Row coordinate of bottom-right corner (exclusive)
     721 */
     722static void term_buf_update(con_srv_t *srv, sysarg_t c0, sysarg_t r0,
     723    sysarg_t c1, sysarg_t r1)
     724{
     725        terminal_t *term = srv_to_terminal(srv);
     726        charfield_t *ch;
     727        sysarg_t col, row;
     728
     729        fibril_mutex_lock(&term->mtx);
     730
     731        if (term->ubuf == NULL) {
     732                fibril_mutex_unlock(&term->mtx);
     733                return;
     734        }
     735
     736        /* Make sure we have meaningful coordinates, within bounds */
     737
     738        if (c1 > term->ucols)
     739                c1 = term->ucols;
     740        if (c1 > term->cols)
     741                c1 = term->cols;
     742        if (c0 >= c1) {
     743                fibril_mutex_unlock(&term->mtx);
     744                return;
     745        }
     746        if (r1 > term->urows)
     747                r1 = term->urows;
     748        if (r1 > term->rows)
     749                r1 = term->rows;
     750        if (r0 >= r1) {
     751                fibril_mutex_unlock(&term->mtx);
     752                return;
     753        }
     754
     755        /* Update front buffer from user buffer */
     756
     757        for (row = r0; row < r1; row++) {
     758                for (col = c0; col < c1; col++) {
     759                        ch = chargrid_charfield_at(term->frontbuf, col, row);
     760                        *ch = term->ubuf[row * term->ucols + col];
     761                }
     762        }
     763
     764        fibril_mutex_unlock(&term->mtx);
     765
     766        /* Update terminal */
     767        term_update(term);
     768        gfx_update(term->gc);
     769}
     770
    647771static void deinit_terminal(terminal_t *term)
    648772{
  • uspace/app/terminal/terminal.h

    r2ab8ab3 r68a552f  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * Copyright (c) 2012 Petr Koupy
    44 * All rights reserved.
     
    8585        sysarg_t top_row;
    8686
     87        sysarg_t ucols;
     88        sysarg_t urows;
     89        charfield_t *ubuf;
     90
    8791        service_id_t dsid;
    8892        con_srvs_t srvs;
  • uspace/lib/c/generic/io/con_srv.c

    r2ab8ab3 r68a552f  
    11/*
    2  * Copyright (c) 2012 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3434 * @brief Console protocol server stub
    3535 */
     36#include <as.h>
    3637#include <errno.h>
    3738#include <io/cons_event.h>
     
    307308}
    308309
     310/** Create shared buffer for efficient rendering */
     311static void con_map_srv(con_srv_t *srv, ipc_call_t *icall)
     312{
     313        errno_t rc;
     314        charfield_t *buf;
     315        sysarg_t cols, rows;
     316        ipc_call_t call;
     317        size_t size;
     318
     319        if (srv->srvs->ops->map == NULL || srv->srvs->ops->unmap == NULL) {
     320                async_answer_0(icall, ENOTSUP);
     321                return;
     322        }
     323
     324        cols = ipc_get_arg1(icall);
     325        rows = ipc_get_arg2(icall);
     326
     327        if (!async_share_in_receive(&call, &size)) {
     328                async_answer_0(icall, EINVAL);
     329                return;
     330        }
     331
     332        /* Check size */
     333        if (size != PAGES2SIZE(SIZE2PAGES(cols * rows * sizeof(charfield_t)))) {
     334                async_answer_0(&call, EINVAL);
     335                async_answer_0(icall, EINVAL);
     336                return;
     337        }
     338
     339        rc = srv->srvs->ops->map(srv, cols, rows, &buf);
     340        if (rc != EOK) {
     341                async_answer_0(&call, rc);
     342                async_answer_0(icall, rc);
     343                return;
     344        }
     345
     346        rc = async_share_in_finalize(&call, buf, AS_AREA_READ |
     347            AS_AREA_WRITE | AS_AREA_CACHEABLE);
     348        if (rc != EOK) {
     349                srv->srvs->ops->unmap(srv);
     350                async_answer_0(icall, EIO);
     351                return;
     352        }
     353
     354        async_answer_0(icall, EOK);
     355}
     356
     357/** Delete shared buffer */
     358static void con_unmap_srv(con_srv_t *srv, ipc_call_t *icall)
     359{
     360        if (srv->srvs->ops->unmap == NULL) {
     361                async_answer_0(icall, ENOTSUP);
     362                return;
     363        }
     364
     365        srv->srvs->ops->unmap(srv);
     366        async_answer_0(icall, EOK);
     367}
     368
     369/** Update console area from shared buffer */
     370static void con_update_srv(con_srv_t *srv, ipc_call_t *icall)
     371{
     372        sysarg_t c0, r0, c1, r1;
     373
     374        c0 = ipc_get_arg1(icall);
     375        r0 = ipc_get_arg2(icall);
     376        c1 = ipc_get_arg3(icall);
     377        r1 = ipc_get_arg4(icall);
     378
     379        if (srv->srvs->ops->update == NULL) {
     380                async_answer_0(icall, ENOTSUP);
     381                return;
     382        }
     383
     384        srv->srvs->ops->update(srv, c0, r0, c1, r1);
     385        async_answer_0(icall, EOK);
     386}
     387
    309388static con_srv_t *con_srv_create(con_srvs_t *srvs)
    310389{
     
    412491                        con_get_event_srv(srv, &call);
    413492                        break;
     493                case CONSOLE_MAP:
     494                        con_map_srv(srv, &call);
     495                        break;
     496                case CONSOLE_UNMAP:
     497                        con_unmap_srv(srv, &call);
     498                        break;
     499                case CONSOLE_UPDATE:
     500                        con_update_srv(srv, &call);
     501                        break;
    414502                default:
    415503                        async_answer_0(&call, ENOTSUP);
  • uspace/lib/c/generic/io/console.c

    r2ab8ab3 r68a552f  
    11/*
     2 * Copyright (c) 2021 Jiri Svoboda
    23 * Copyright (c) 2006 Josef Cejka
    34 * Copyright (c) 2006 Jakub Vana
    4  * Copyright (c) 2008 Jiri Svoboda
    55 * All rights reserved.
    66 *
     
    3535 */
    3636
     37#include <as.h>
    3738#include <libc.h>
    3839#include <async.h>
     
    264265}
    265266
     267/** Create a shared buffer for fast rendering to the console.
     268 *
     269 * @param ctrl Console
     270 * @param cols Number of columns
     271 * @param rows Number of rows
     272 * @param rbuf Place to store pointer to the shared buffer
     273 * @return EOK on success or an error code
     274 */
     275errno_t console_map(console_ctrl_t *ctrl, sysarg_t cols, sysarg_t rows,
     276    charfield_t **rbuf)
     277{
     278        async_exch_t *exch = NULL;
     279        void *buf;
     280        aid_t req;
     281        ipc_call_t answer;
     282        size_t asize;
     283        errno_t rc;
     284
     285        exch = async_exchange_begin(ctrl->output_sess);
     286        req = async_send_2(exch, CONSOLE_MAP, cols, rows, &answer);
     287        if (rc != EOK)
     288                goto error;
     289
     290        asize = PAGES2SIZE(SIZE2PAGES(cols * rows * sizeof(charfield_t)));
     291
     292        rc = async_share_in_start_0_0(exch, asize, &buf);
     293        if (rc != EOK) {
     294                async_forget(req);
     295                goto error;
     296        }
     297
     298        async_exchange_end(exch);
     299        exch = NULL;
     300
     301        async_wait_for(req, &rc);
     302        if (rc != EOK)
     303                goto error;
     304
     305        *rbuf = (charfield_t *)buf;
     306        return EOK;
     307error:
     308        if (exch != NULL)
     309                async_exchange_end(exch);
     310        return rc;
     311}
     312
     313/** Unmap console shared buffer.
     314 *
     315 * @param ctrl Console
     316 * @param buf Buffer
     317 */
     318void console_unmap(console_ctrl_t *ctrl, charfield_t *buf)
     319{
     320        as_area_destroy(buf);
     321}
     322
     323/** Update console rectangle from shared buffer.
     324 *
     325 * @param ctrl Console
     326 * @param c0 Column coordinate of top-left corner (inclusive)
     327 * @param r0 Row coordinate of top-left corner (inclusive)
     328 * @param c1 Column coordinate of bottom-right corner (exclusive)
     329 * @param r1 Row coordinate of bottom-right corner (exclusive)
     330 *
     331 * @return EOK on sucess or an error code
     332 */
     333errno_t console_update(console_ctrl_t *ctrl, sysarg_t c0, sysarg_t r0,
     334    sysarg_t c1, sysarg_t r1)
     335{
     336        async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
     337        errno_t rc = async_req_4_0(exch, CONSOLE_UPDATE, c0, r0, c1, r1);
     338        async_exchange_end(exch);
     339
     340        return rc;
     341}
     342
    266343/** @}
    267344 */
  • uspace/lib/c/include/io/con_srv.h

    r2ab8ab3 r68a552f  
    11/*
    2  * Copyright (c) 2012 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939#include <async.h>
    4040#include <fibril_synch.h>
     41#include <io/charfield.h>
    4142#include <io/color.h>
    4243#include <io/concaps.h>
     
    8384        void (*set_cursor_visibility)(con_srv_t *, bool);
    8485        errno_t (*get_event)(con_srv_t *, cons_event_t *);
     86        errno_t (*map)(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
     87        void (*unmap)(con_srv_t *);
     88        void (*update)(con_srv_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
    8589};
    8690
  • uspace/lib/c/include/io/console.h

    r2ab8ab3 r68a552f  
    11/*
    2  * Copyright (c) 2008 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3737
    3838#include <time.h>
     39#include <io/charfield.h>
    3940#include <io/concaps.h>
    4041#include <io/kbd_event.h>
     
    8687extern bool console_get_event_timeout(console_ctrl_t *, cons_event_t *,
    8788    usec_t *);
     89extern errno_t console_map(console_ctrl_t *, sysarg_t, sysarg_t,
     90    charfield_t **);
     91extern void console_unmap(console_ctrl_t *, charfield_t *);
     92extern errno_t console_update(console_ctrl_t *, sysarg_t, sysarg_t, sysarg_t,
     93    sysarg_t);
    8894
    8995#endif
  • uspace/lib/c/include/ipc/console.h

    r2ab8ab3 r68a552f  
    11/*
     2 * Copyright (c) 2021 Jiri Svoboda
    23 * Copyright (c) 2006 Josef Cejka
    34 * All rights reserved.
     
    4849        CONSOLE_SET_COLOR,
    4950        CONSOLE_SET_RGB_COLOR,
    50         CONSOLE_SET_CURSOR_VISIBILITY
     51        CONSOLE_SET_CURSOR_VISIBILITY,
     52        CONSOLE_MAP,
     53        CONSOLE_UNMAP,
     54        CONSOLE_UPDATE
    5155} console_request_t;
    5256
  • uspace/lib/congfx/private/console.h

    r2ab8ab3 r68a552f  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939
    4040#include <gfx/context.h>
     41#include <io/charfield.h>
    4142#include <io/console.h>
    4243#include <io/pixel.h>
     
    5859        /** Current drawing color */
    5960        pixel_t clr;
     61        /** Shared console buffer */
     62        charfield_t *buf;
    6063};
    6164
  • uspace/lib/congfx/src/console.c

    r2ab8ab3 r68a552f  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    9292{
    9393        console_gc_t *cgc = (console_gc_t *) arg;
    94         int rv;
    9594        gfx_coord_t x, y;
    96 
    97         // XXX We should handle p0.x > p1.x and p0.y > p1.y
    98 
    99         console_set_rgb_color(cgc->con, cgc->clr, cgc->clr);
    100 
    101         for (y = rect->p0.y; y < rect->p1.y; y++) {
    102                 console_set_pos(cgc->con, rect->p0.x, y);
    103 
    104                 for (x = rect->p0.x; x < rect->p1.x; x++) {
    105                         rv = fputc('X', cgc->fout);
    106                         if (rv < 0)
    107                                 return EIO;
    108                 }
    109 
    110                 console_flush(cgc->con);
    111         }
     95        gfx_coord_t cols;
     96        gfx_rect_t crect;
     97        charfield_t ch;
     98
     99        /* Make sure rectangle is clipped and sorted */
     100        gfx_rect_clip(rect, &cgc->rect, &crect);
     101
     102        cols = cgc->rect.p1.x - cgc->rect.p0.x;
     103
     104        ch.ch = 0;
     105        ch.flags = CHAR_FLAG_DIRTY;
     106        ch.attrs.type = CHAR_ATTR_RGB;
     107        ch.attrs.val.rgb.fgcolor = cgc->clr;
     108        ch.attrs.val.rgb.bgcolor = cgc->clr;
     109
     110        for (y = crect.p0.y; y < crect.p1.y; y++) {
     111                for (x = crect.p0.x; x < crect.p1.x; x++) {
     112                        cgc->buf[y * cols + x] = ch;
     113                }
     114        }
     115
     116        console_update(cgc->con, crect.p0.x, crect.p0.y,
     117            crect.p1.x, crect.p1.y);
    112118
    113119        return EOK;
     
    131137        sysarg_t rows;
    132138        sysarg_t cols;
     139        charfield_t *buf;
    133140        errno_t rc;
    134141
     
    140147
    141148        rc = console_get_size(con, &cols, &rows);
     149        if (rc != EOK)
     150                goto error;
     151
     152        rc = console_map(con, cols, rows, &buf);
    142153        if (rc != EOK)
    143154                goto error;
     
    154165        cgc->rect.p1.x = cols;
    155166        cgc->rect.p1.y = rows - 1; /* make sure we avoid bottom-right corner */
     167        cgc->buf = buf;
    156168
    157169        *rgc = cgc;
     
    268280        console_gc_bitmap_t *cbm = (console_gc_bitmap_t *)bm;
    269281        gfx_coord_t x, y;
    270         int rv;
    271282        pixel_t clr;
     283        charfield_t ch;
    272284        pixelmap_t pixelmap;
    273285        gfx_rect_t srect;
     
    275287        gfx_rect_t crect;
    276288        gfx_coord2_t offs;
     289        gfx_coord_t cols;
    277290
    278291        if (srect0 != NULL)
     
    295308        pixelmap.data = cbm->alloc.pixels;
    296309
     310        cols = cbm->cgc->rect.p1.x - cbm->cgc->rect.p0.x;
     311
    297312        if ((cbm->flags & bmpf_color_key) == 0) {
    298313                /* Simple copy */
     
    304319                                    x - offs.x - cbm->rect.p0.x,
    305320                                    y - offs.y - cbm->rect.p0.y);
    306                                 console_set_rgb_color(cbm->cgc->con, clr, clr);
    307 
    308                                 rv = fputc('X', cbm->cgc->fout);
    309                                 if (rv < 0)
    310                                         return EIO;
    311 
    312                                 console_flush(cbm->cgc->con);
     321
     322                                ch.ch = 0;
     323                                ch.flags = CHAR_FLAG_DIRTY;
     324                                ch.attrs.type = CHAR_ATTR_RGB;
     325                                ch.attrs.val.rgb.fgcolor = clr;
     326                                ch.attrs.val.rgb.bgcolor = clr;
     327
     328                                cbm->cgc->buf[y * cols + x] = ch;
    313329                        }
    314330                }
     
    321337                                    x - offs.x - cbm->rect.p0.x,
    322338                                    y - offs.y - cbm->rect.p0.y);
    323                                 console_set_rgb_color(cbm->cgc->con, clr, clr);
    324 
    325                                 if (clr != cbm->key_color) {
    326                                         console_set_pos(cbm->cgc->con, x, y);
    327                                         rv = fputc('X', cbm->cgc->fout);
    328                                         if (rv < 0)
    329                                                 return EIO;
    330 
    331                                         console_flush(cbm->cgc->con);
    332                                 }
    333 
     339
     340                                ch.ch = 0;
     341                                ch.flags = CHAR_FLAG_DIRTY;
     342                                ch.attrs.type = CHAR_ATTR_RGB;
     343                                ch.attrs.val.rgb.fgcolor = clr;
     344                                ch.attrs.val.rgb.bgcolor = clr;
     345
     346                                if (clr != cbm->key_color)
     347                                        cbm->cgc->buf[y * cols + x] = ch;
    334348                        }
    335349                }
     
    338352                console_set_rgb_color(cbm->cgc->con, cbm->cgc->clr,
    339353                    cbm->cgc->clr);
     354                ch.ch = 0;
     355                ch.flags = CHAR_FLAG_DIRTY;
     356                ch.attrs.type = CHAR_ATTR_RGB;
     357                ch.attrs.val.rgb.fgcolor = cbm->cgc->clr;
     358                ch.attrs.val.rgb.bgcolor = cbm->cgc->clr;
    340359
    341360                for (y = crect.p0.y; y < crect.p1.y; y++) {
    342361                        for (x = crect.p0.x; x < crect.p1.x; x++) {
    343 
    344362                                clr = pixelmap_get_pixel(&pixelmap,
    345363                                    x - offs.x - cbm->rect.p0.x,
    346364                                    y - offs.y - cbm->rect.p0.y);
    347365
    348                                 if (clr != cbm->key_color) {
    349                                         console_set_pos(cbm->cgc->con, x, y);
    350                                         rv = fputc('X', cbm->cgc->fout);
    351                                         if (rv < 0)
    352                                                 return EIO;
    353 
    354                                         console_flush(cbm->cgc->con);
    355                                 }
    356 
     366                                if (clr != cbm->key_color)
     367                                        cbm->cgc->buf[y * cols + x] = ch;
    357368                        }
    358369                }
    359370        }
     371
     372        console_update(cbm->cgc->con, crect.p0.x, crect.p0.y, crect.p1.x,
     373            crect.p1.y);
    360374
    361375        return EOK;
  • uspace/srv/hid/console/console.c

    r2ab8ab3 r68a552f  
    11/*
     2 * Copyright (c) 2021 Jiri Svoboda
    23 * Copyright (c) 2011 Martin Decky
    34 * All rights reserved.
     
    7980        console_caps_t ccaps;  /**< Console capabilities */
    8081
     82        sysarg_t ucols;         /**< Number of columns in user buffer */
     83        sysarg_t urows;         /**< Number of rows in user buffer */
     84        charfield_t *ubuf;      /**< User buffer */
     85
    8186        chargrid_t *frontbuf;    /**< Front buffer */
    8287        frontbuf_handle_t fbid;  /**< Front buffer handle */
     
    135140static void cons_set_cursor_visibility(con_srv_t *, bool);
    136141static errno_t cons_get_event(con_srv_t *, cons_event_t *);
     142static errno_t cons_map(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
     143static void cons_unmap(con_srv_t *);
     144static void cons_buf_update(con_srv_t *, sysarg_t, sysarg_t, sysarg_t,
     145    sysarg_t);
    137146
    138147static con_ops_t con_ops = {
     
    151160        .set_rgb_color = cons_set_rgb_color,
    152161        .set_cursor_visibility = cons_set_cursor_visibility,
    153         .get_event = cons_get_event
     162        .get_event = cons_get_event,
     163        .map = cons_map,
     164        .unmap = cons_unmap,
     165        .update = cons_buf_update
    154166};
    155167
     
    508520}
    509521
     522/** Create shared buffer for efficient rendering.
     523 *
     524 * @param srv Console server
     525 * @param cols Number of columns in buffer
     526 * @param rows Number of rows in buffer
     527 * @param rbuf Place to store pointer to new sharable buffer
     528 *
     529 * @return EOK on sucess or an error code
     530 */
     531static errno_t cons_map(con_srv_t *srv, sysarg_t cols, sysarg_t rows,
     532    charfield_t **rbuf)
     533{
     534        console_t *cons = srv_to_console(srv);
     535        void *buf;
     536
     537        fibril_mutex_lock(&cons->mtx);
     538
     539        if (cons->ubuf != NULL) {
     540                fibril_mutex_unlock(&cons->mtx);
     541                return EBUSY;
     542        }
     543
     544        buf = as_area_create(AS_AREA_ANY, cols * rows * sizeof(charfield_t),
     545            AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, AS_AREA_UNPAGED);
     546        if (buf == AS_MAP_FAILED) {
     547                fibril_mutex_unlock(&cons->mtx);
     548                return ENOMEM;
     549        }
     550
     551        cons->ucols = cols;
     552        cons->urows = rows;
     553        cons->ubuf = buf;
     554        fibril_mutex_unlock(&cons->mtx);
     555
     556        *rbuf = buf;
     557        return EOK;
     558}
     559
     560/** Delete shared buffer.
     561 *
     562 * @param srv Console server
     563 */
     564static void cons_unmap(con_srv_t *srv)
     565{
     566        console_t *cons = srv_to_console(srv);
     567        void *buf;
     568
     569        fibril_mutex_lock(&cons->mtx);
     570
     571        buf = cons->ubuf;
     572        cons->ubuf = NULL;
     573
     574        if (buf != NULL)
     575                as_area_destroy(buf);
     576
     577        fibril_mutex_unlock(&cons->mtx);
     578}
     579
     580/** Update area of console from shared buffer.
     581 *
     582 * @param srv Console server
     583 * @param c0 Column coordinate of top-left corner (inclusive)
     584 * @param r0 Row coordinate of top-left corner (inclusive)
     585 * @param c1 Column coordinate of bottom-right corner (exclusive)
     586 * @param r1 Row coordinate of bottom-right corner (exclusive)
     587 */
     588static void cons_buf_update(con_srv_t *srv, sysarg_t c0, sysarg_t r0,
     589    sysarg_t c1, sysarg_t r1)
     590{
     591        console_t *cons = srv_to_console(srv);
     592        charfield_t *ch;
     593        sysarg_t col, row;
     594
     595        fibril_mutex_lock(&cons->mtx);
     596
     597        if (cons->ubuf == NULL) {
     598                fibril_mutex_unlock(&cons->mtx);
     599                return;
     600        }
     601
     602        /* Make sure we have meaningful coordinates, within bounds */
     603
     604        if (c1 > cons->ucols)
     605                c1 = cons->ucols;
     606        if (c1 > cons->cols)
     607                c1 = cons->cols;
     608        if (c0 >= c1) {
     609                fibril_mutex_unlock(&cons->mtx);
     610                return;
     611        }
     612        if (r1 > cons->urows)
     613                r1 = cons->urows;
     614        if (r1 > cons->rows)
     615                r1 = cons->rows;
     616        if (r0 >= r1) {
     617                fibril_mutex_unlock(&cons->mtx);
     618                return;
     619        }
     620
     621        /* Update front buffer from user buffer */
     622
     623        for (row = r0; row < r1; row++) {
     624                for (col = c0; col < c1; col++) {
     625                        ch = chargrid_charfield_at(cons->frontbuf, col, row);
     626                        *ch = cons->ubuf[row * cons->ucols + col];
     627                }
     628        }
     629
     630        fibril_mutex_unlock(&cons->mtx);
     631
     632        /* Update console */
     633        cons_update(cons);
     634}
     635
    510636static void client_connection(ipc_call_t *icall, void *arg)
    511637{
Note: See TracChangeset for help on using the changeset viewer.