Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/congfx/src/console.c

    r0d62c10 ra4e4e29  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4848#include "../private/color.h"
    4949
     50static errno_t console_gc_set_clip_rect(void *, gfx_rect_t *);
    5051static errno_t console_gc_set_color(void *, gfx_color_t *);
    5152static errno_t console_gc_fill_rect(void *, gfx_rect_t *);
     53static errno_t console_gc_update(void *);
    5254static errno_t console_gc_bitmap_create(void *, gfx_bitmap_params_t *,
    5355    gfx_bitmap_alloc_t *, void **);
     
    5557static errno_t console_gc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
    5658static errno_t console_gc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
     59static errno_t console_gc_cursor_get_pos(void *, gfx_coord2_t *);
     60static errno_t console_gc_cursor_set_pos(void *, gfx_coord2_t *);
     61static errno_t console_gc_cursor_set_visible(void *, bool);
    5762
    5863gfx_context_ops_t console_gc_ops = {
     64        .set_clip_rect = console_gc_set_clip_rect,
    5965        .set_color = console_gc_set_color,
    6066        .fill_rect = console_gc_fill_rect,
     67        .update = console_gc_update,
    6168        .bitmap_create = console_gc_bitmap_create,
    6269        .bitmap_destroy = console_gc_bitmap_destroy,
    6370        .bitmap_render = console_gc_bitmap_render,
    64         .bitmap_get_alloc = console_gc_bitmap_get_alloc
     71        .bitmap_get_alloc = console_gc_bitmap_get_alloc,
     72        .cursor_get_pos = console_gc_cursor_get_pos,
     73        .cursor_set_pos = console_gc_cursor_set_pos,
     74        .cursor_set_visible = console_gc_cursor_set_visible
    6575};
    6676
     77/** Convert pixel value to charfield.
     78 *
     79 * On the bottom of this function lies a big big hack. In the absence
     80 * of support for different color formats (FIX ME!), here's a single
     81 * format that can represent both 3x8bit RGB and 24-bit characters
     82 * with 8-bit EGA attributes (i.e. we can specify the foreground and
     83 * background colors individually).
     84 *
     85 * A    R   G   B
     86 * 0    red grn blu  24-bit color
     87 * attr c2  c1  c0   attribute + 24-bit character
     88 */
     89static void console_gc_pix_to_charfield(pixel_t clr, charfield_t *ch)
     90{
     91        uint8_t attr;
     92
     93        if ((clr >> 24) == 0xff) {
     94                /* RGB (no text) */
     95                ch->ch = 0;
     96                ch->flags = CHAR_FLAG_DIRTY;
     97                ch->attrs.type = CHAR_ATTR_RGB;
     98                ch->attrs.val.rgb.fgcolor = clr;
     99                ch->attrs.val.rgb.bgcolor = clr;
     100        } else {
     101                /* EGA attributes (with text) */
     102                attr = clr >> 24;
     103                ch->ch = clr & 0xffffff;
     104                ch->flags = CHAR_FLAG_DIRTY;
     105                ch->attrs.type = CHAR_ATTR_INDEX;
     106                ch->attrs.val.index.fgcolor = attr & 0x7;
     107                ch->attrs.val.index.bgcolor = (attr >> 4) & 0x7;
     108                ch->attrs.val.index.attr =
     109                    ((attr & 0x8) ? CATTR_BRIGHT : 0) +
     110                    ((attr & 0x80) ? CATTR_BLINK : 0);
     111        }
     112}
     113
     114/** Set clipping rectangle on console GC.
     115 *
     116 * @param arg Console GC
     117 * @param rect Rectangle
     118 *
     119 * @return EOK on success or an error code
     120 */
     121static errno_t console_gc_set_clip_rect(void *arg, gfx_rect_t *rect)
     122{
     123        console_gc_t *cgc = (console_gc_t *) arg;
     124
     125        if (rect != NULL)
     126                gfx_rect_clip(rect, &cgc->rect, &cgc->clip_rect);
     127        else
     128                cgc->clip_rect = cgc->rect;
     129
     130        return EOK;
     131}
     132
    67133/** Set color on console GC.
    68134 *
     
    78144        console_gc_t *cgc = (console_gc_t *) arg;
    79145
    80         cgc->clr = PIXEL(0, color->r >> 8, color->g >> 8, color->b >> 8);
     146        cgc->clr = PIXEL(color->attr, color->r >> 8, color->g >> 8, color->b >> 8);
    81147        return EOK;
    82148}
     
    92158{
    93159        console_gc_t *cgc = (console_gc_t *) arg;
    94         int rv;
    95160        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;
     161        gfx_coord_t cols;
     162        gfx_rect_t crect;
     163        charfield_t ch;
     164
     165        /* Make sure rectangle is clipped and sorted */
     166        gfx_rect_clip(rect, &cgc->clip_rect, &crect);
     167
     168        cols = cgc->rect.p1.x - cgc->rect.p0.x;
     169
     170        console_gc_pix_to_charfield(cgc->clr, &ch);
     171
     172        for (y = crect.p0.y; y < crect.p1.y; y++) {
     173                for (x = crect.p0.x; x < crect.p1.x; x++) {
     174                        cgc->buf[y * cols + x] = ch;
    108175                }
    109 
    110                 console_flush(cgc->con);
    111176        }
    112177
     178        console_update(cgc->con, crect.p0.x, crect.p0.y,
     179            crect.p1.x, crect.p1.y);
     180
     181        return EOK;
     182}
     183
     184/** Update console GC.
     185 *
     186 * @param arg Console GC
     187 *
     188 * @return EOK on success or an error code
     189 */
     190static errno_t console_gc_update(void *arg)
     191{
     192        console_gc_t *cgc = (console_gc_t *) arg;
     193
     194        /*
     195         * XXX Before actually deferring update to here (and similarly other
     196         * GC implementations) need to make sure all consumers properly
     197         * call update.
     198         */
     199        (void) cgc;
    113200        return EOK;
    114201}
     
    131218        sysarg_t rows;
    132219        sysarg_t cols;
     220        charfield_t *buf = NULL;
    133221        errno_t rc;
    134222
     
    140228
    141229        rc = console_get_size(con, &cols, &rows);
     230        if (rc != EOK)
     231                goto error;
     232
     233        console_clear(con);
     234
     235        rc = console_map(con, cols, rows, &buf);
    142236        if (rc != EOK)
    143237                goto error;
     
    153247        cgc->rect.p0.y = 0;
    154248        cgc->rect.p1.x = cols;
    155         cgc->rect.p1.y = rows - 1; /* make sure we avoid bottom-right corner */
     249        cgc->rect.p1.y = rows;
     250        cgc->clip_rect = cgc->rect;
     251        cgc->buf = buf;
    156252
    157253        *rgc = cgc;
    158254        return EOK;
    159255error:
     256        if (buf != NULL)
     257                console_unmap(cgc->con, buf);
    160258        if (cgc != NULL)
    161259                free(cgc);
     
    176274                return rc;
    177275
     276        console_clear(cgc->con);
     277        console_unmap(cgc->con, cgc->buf);
     278
    178279        free(cgc);
    179280        return EOK;
    180281}
     282
     283/** Free up console for other users, suspending GC operation.
     284 *
     285 * @param cgc Console GC
     286 * @return EOK on success or an error code
     287 */
     288errno_t console_gc_suspend(console_gc_t *cgc)
     289{
     290        console_unmap(cgc->con, cgc->buf);
     291        cgc->buf = NULL;
     292
     293        console_clear(cgc->con);
     294        console_cursor_visibility(cgc->con, true);
     295        return EOK;
     296}
     297
     298/** Resume GC operation after suspend.
     299 *
     300 * @param cgc Console GC
     301 * @return EOK on success or an error code
     302 */
     303errno_t console_gc_resume(console_gc_t *cgc)
     304{
     305        errno_t rc;
     306
     307        console_clear(cgc->con);
     308
     309        rc = console_map(cgc->con, cgc->rect.p1.x, cgc->rect.p1.y, &cgc->buf);
     310        if (rc != EOK)
     311                return rc;
     312
     313        return EOK;
     314}
     315
     316/** Update console GC size after console resize.
     317 *
     318 * @param con Console object
     319 *
     320 * @return EOK on success or an error code
     321 */
     322errno_t console_gc_resize(console_gc_t *cgc)
     323{
     324        sysarg_t rows;
     325        sysarg_t cols;
     326        charfield_t *buf = NULL;
     327        errno_t rc;
     328
     329        console_unmap(cgc->con, cgc->buf);
     330        cgc->buf = NULL;
     331
     332        rc = console_get_size(cgc->con, &cols, &rows);
     333        if (rc != EOK)
     334                goto error;
     335
     336        rc = console_map(cgc->con, cols, rows, &buf);
     337        if (rc != EOK)
     338                goto error;
     339
     340        cgc->rect.p0.x = 0;
     341        cgc->rect.p0.y = 0;
     342        cgc->rect.p1.x = cols;
     343        cgc->rect.p1.y = rows;
     344        cgc->clip_rect = cgc->rect;
     345        cgc->buf = buf;
     346        return EOK;
     347error:
     348        return rc;
     349}
     350
    181351
    182352/** Get generic graphic context from console GC.
     
    268438        console_gc_bitmap_t *cbm = (console_gc_bitmap_t *)bm;
    269439        gfx_coord_t x, y;
    270         int rv;
    271440        pixel_t clr;
     441        charfield_t ch;
    272442        pixelmap_t pixelmap;
    273443        gfx_rect_t srect;
     
    275445        gfx_rect_t crect;
    276446        gfx_coord2_t offs;
     447        gfx_coord_t cols;
    277448
    278449        if (srect0 != NULL)
     
    289460
    290461        gfx_rect_translate(&offs, &srect, &drect);
    291         gfx_rect_clip(&drect, &cbm->cgc->rect, &crect);
     462        gfx_rect_clip(&drect, &cbm->cgc->clip_rect, &crect);
    292463
    293464        pixelmap.width = cbm->rect.p1.x - cbm->rect.p0.x;
     
    295466        pixelmap.data = cbm->alloc.pixels;
    296467
     468        cols = cbm->cgc->rect.p1.x - cbm->cgc->rect.p0.x;
     469
    297470        if ((cbm->flags & bmpf_color_key) == 0) {
    298471                /* Simple copy */
    299472                for (y = crect.p0.y; y < crect.p1.y; y++) {
    300                         console_set_pos(cbm->cgc->con, crect.p0.x, y);
    301 
    302473                        for (x = crect.p0.x; x < crect.p1.x; x++) {
    303474                                clr = pixelmap_get_pixel(&pixelmap,
    304475                                    x - offs.x - cbm->rect.p0.x,
    305476                                    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);
     477
     478                                console_gc_pix_to_charfield(clr, &ch);
     479                                cbm->cgc->buf[y * cols + x] = ch;
    313480                        }
    314481                }
     
    321488                                    x - offs.x - cbm->rect.p0.x,
    322489                                    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 
     490
     491                                console_gc_pix_to_charfield(clr, &ch);
     492
     493                                if (clr != cbm->key_color)
     494                                        cbm->cgc->buf[y * cols + x] = ch;
    334495                        }
    335496                }
    336497        } else {
    337498                /* Color key & colorize */
    338                 console_set_rgb_color(cbm->cgc->con, cbm->cgc->clr,
    339                     cbm->cgc->clr);
     499                console_gc_pix_to_charfield(cbm->cgc->clr, &ch);
    340500
    341501                for (y = crect.p0.y; y < crect.p1.y; y++) {
    342502                        for (x = crect.p0.x; x < crect.p1.x; x++) {
    343 
    344503                                clr = pixelmap_get_pixel(&pixelmap,
    345504                                    x - offs.x - cbm->rect.p0.x,
    346505                                    y - offs.y - cbm->rect.p0.y);
    347506
    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 
     507                                if (clr != cbm->key_color)
     508                                        cbm->cgc->buf[y * cols + x] = ch;
    357509                        }
    358510                }
    359511        }
    360512
     513        console_update(cbm->cgc->con, crect.p0.x, crect.p0.y, crect.p1.x,
     514            crect.p1.y);
     515
    361516        return EOK;
    362517}
     
    375530}
    376531
     532/** Get cursor position on console GC.
     533 *
     534 * @param arg Console GC
     535 * @param pos Place to store position
     536 *
     537 * @return EOK on success or an error code
     538 */
     539static errno_t console_gc_cursor_get_pos(void *arg, gfx_coord2_t *pos)
     540{
     541        console_gc_t *cgc = (console_gc_t *) arg;
     542        sysarg_t col;
     543        sysarg_t row;
     544        errno_t rc;
     545
     546        rc = console_get_pos(cgc->con, &col, &row);
     547        if (rc != EOK)
     548                return rc;
     549
     550        pos->x = col;
     551        pos->y = row;
     552        return EOK;
     553}
     554
     555/** Set cursor position on console GC.
     556 *
     557 * @param arg Console GC
     558 * @param pos New cursor position
     559 *
     560 * @return EOK on success or an error code
     561 */
     562static errno_t console_gc_cursor_set_pos(void *arg, gfx_coord2_t *pos)
     563{
     564        console_gc_t *cgc = (console_gc_t *) arg;
     565
     566        console_set_pos(cgc->con, pos->x, pos->y);
     567        return EOK;
     568}
     569
     570/** Set cursor visibility on console GC.
     571 *
     572 * @param arg Console GC
     573 * @param visible @c true iff cursor should be made visible
     574 *
     575 * @return EOK on success or an error code
     576 */
     577static errno_t console_gc_cursor_set_visible(void *arg, bool visible)
     578{
     579        console_gc_t *cgc = (console_gc_t *) arg;
     580
     581        console_cursor_visibility(cgc->con, visible);
     582        return EOK;
     583}
     584
    377585/** @}
    378586 */
Note: See TracChangeset for help on using the changeset viewer.