Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/fb/fb.c

    rde96d3b r888c06e  
    8181        ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
    8282
     83#define TAB_WIDTH 8
     84
    8385typedef void (*rgb_conv_t)(void *, uint32_t);
    8486
     
    99101
    100102        /** Number of rows that fit on framebuffer */
    101         unsigned int rowtrim;
     103        unsigned int screen_rows;
    102104
    103105        unsigned int scanline;
     
    121123        /** Current backbuffer position */
    122124        unsigned int position;
     125
     126        /** Partial character between writes */
     127        mbstate_t mbstate;
     128
     129        unsigned int row;
     130        unsigned int column;
    123131} fb_instance_t;
    124132
    125 static void fb_putuchar(outdev_t *, char32_t);
     133static void fb_write(outdev_t *, const char *, size_t);
    126134static void fb_redraw(outdev_t *);
    127135static void fb_scroll_up(outdev_t *);
     
    129137
    130138static outdev_operations_t fbdev_ops = {
    131         .write = fb_putuchar,
     139        .write = fb_write,
    132140        .redraw = fb_redraw,
    133141        .scroll_up = fb_scroll_up,
     
    247255
    248256        unsigned int rel_row = row - instance->offset_row;
    249         if (rel_row >= instance->rowtrim)
     257        if (rel_row >= instance->screen_rows)
    250258                return;
    251259
     
    259267}
    260268
    261 /** Scroll screen down by one row
    262  *
    263  */
    264 static void screen_scroll(fb_instance_t *instance)
    265 {
    266         if ((!instance->parea.mapped) || (console_override)) {
    267                 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
    268                         unsigned int y = ROW2Y(rel_row);
    269                         unsigned int row = rel_row + instance->offset_row;
    270 
    271                         for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
    272                                 unsigned int x;
    273                                 unsigned int col;
    274                                 size_t bb_pos = BB_POS(instance, 0, row);
    275                                 size_t bb_pos1 = BB_POS(instance, 0, row + 1);
    276 
    277                                 for (col = 0, x = 0; col < instance->cols;
    278                                     col++, x += FONT_WIDTH) {
    279                                         uint16_t glyph;
    280 
    281                                         if (row < instance->rows - 1) {
    282                                                 if (instance->backbuf[bb_pos] ==
    283                                                     instance->backbuf[bb_pos1])
    284                                                         goto skip;
    285 
    286                                                 glyph = instance->backbuf[bb_pos1];
    287                                         } else
    288                                                 glyph = 0;
    289 
    290                                         memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
    291                                             &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
    292                                             instance->glyphscanline);
    293                                 skip:
    294                                         BB_NEXT_COL(bb_pos);
    295                                         BB_NEXT_COL(bb_pos1);
    296                                 }
    297                         }
    298                 }
    299         }
    300 
    301         /*
    302          * Implement backbuffer scrolling by wrapping around
    303          * the cyclic buffer.
    304          */
    305 
    306         instance->start_row++;
    307         if (instance->start_row == instance->rows)
    308                 instance->start_row = 0;
    309 
    310         memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
    311             instance->cols, 0);
    312 }
    313 
    314269static void cursor_put(fb_instance_t *instance)
    315270{
    316         unsigned int col = instance->position % instance->cols;
    317         unsigned int row = instance->position / instance->cols;
     271        unsigned int col = instance->column;
     272        unsigned int row = instance->row;
    318273
    319274        glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
     
    322277static void cursor_remove(fb_instance_t *instance)
    323278{
    324         unsigned int col = instance->position % instance->cols;
    325         unsigned int row = instance->position / instance->cols;
     279        unsigned int col = instance->column;
     280        unsigned int row = instance->row;
    326281
    327282        glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
     
    373328static void fb_redraw_internal(fb_instance_t *instance)
    374329{
    375         for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
     330        for (unsigned int rel_row = 0; rel_row < instance->screen_rows; rel_row++) {
    376331                unsigned int y = ROW2Y(rel_row);
    377332                unsigned int row = rel_row + instance->offset_row;
     
    404359        }
    405360
    406         if (ROW2Y(instance->rowtrim) < instance->yres) {
     361        if (ROW2Y(instance->screen_rows) < instance->yres) {
    407362                unsigned int y;
    408363
    409                 for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
     364                for (y = ROW2Y(instance->screen_rows); y < instance->yres; y++)
    410365                        memcpy(&instance->addr[FB_POS(instance, 0, y)],
    411366                            instance->bgscan, instance->bgscanbytes);
     
    413368}
    414369
     370/** Scroll screen down by one row
     371 *
     372 */
     373static void screen_scroll(fb_instance_t *instance)
     374{
     375        /*
     376         * Implement backbuffer scrolling by wrapping around
     377         * the cyclic buffer.
     378         */
     379
     380        instance->start_row++;
     381        if (instance->start_row == instance->rows)
     382                instance->start_row = 0;
     383
     384        if ((!instance->parea.mapped) || (console_override)) {
     385                fb_redraw_internal(instance);
     386        }
     387}
     388
     389static void _advance_row(fb_instance_t *instance)
     390{
     391        instance->column = 0;
     392        instance->row++;
     393}
     394
     395static void _advance_column(fb_instance_t *instance)
     396{
     397        instance->column++;
     398        if (instance->column == instance->cols)
     399                _advance_row(instance);
     400}
     401
    415402/** Print character to screen
    416403 *
     
    418405 *
    419406 */
    420 static void fb_putuchar(outdev_t *dev, char32_t ch)
     407static void _putuchar(fb_instance_t *instance, char32_t ch)
     408{
     409        switch (ch) {
     410        case '\n':
     411                _advance_row(instance);
     412                break;
     413        case '\r':
     414                instance->column = 0;
     415                break;
     416        case '\b':
     417                if (instance->column > 0)
     418                        instance->column--;
     419                break;
     420        case '\t':
     421                do {
     422                        glyph_draw(instance, fb_font_glyph(' '),
     423                            instance->column,
     424                            instance->row, false);
     425                        _advance_column(instance);
     426                } while (instance->column % TAB_WIDTH != 0);
     427                break;
     428        default:
     429                glyph_draw(instance, fb_font_glyph(ch),
     430                    instance->column,
     431                    instance->row, false);
     432                _advance_column(instance);
     433        }
     434
     435        while (instance->row >= instance->rows) {
     436                instance->row--;
     437                screen_scroll(instance);
     438        }
     439}
     440
     441static void fb_write(outdev_t *dev, const char *s, size_t n)
     442{
     443        fb_instance_t *instance = (fb_instance_t *) dev->data;
     444
     445        spinlock_lock(&instance->lock);
     446        cursor_remove(instance);
     447
     448        size_t offset = 0;
     449        char32_t ch;
     450
     451        while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))
     452                _putuchar(instance, ch);
     453
     454        cursor_put(instance);
     455        spinlock_unlock(&instance->lock);
     456}
     457
     458/** Scroll the framebuffer up
     459 *
     460 */
     461static void fb_scroll_up(outdev_t *dev)
    421462{
    422463        fb_instance_t *instance = (fb_instance_t *) dev->data;
    423464        spinlock_lock(&instance->lock);
    424465
    425         switch (ch) {
    426         case '\n':
    427                 cursor_remove(instance);
    428                 instance->position += instance->cols;
    429                 instance->position -= instance->position % instance->cols;
    430                 break;
    431         case '\r':
    432                 cursor_remove(instance);
    433                 instance->position -= instance->position % instance->cols;
    434                 break;
    435         case '\b':
    436                 cursor_remove(instance);
    437                 if (instance->position % instance->cols)
    438                         instance->position--;
    439                 break;
    440         case '\t':
    441                 cursor_remove(instance);
    442                 do {
    443                         glyph_draw(instance, fb_font_glyph(' '),
    444                             instance->position % instance->cols,
    445                             instance->position / instance->cols, false);
    446                         instance->position++;
    447                 } while (((instance->position % instance->cols) % 8 != 0) &&
    448                     (instance->position < instance->cols * instance->rows));
    449                 break;
    450         default:
    451                 glyph_draw(instance, fb_font_glyph(ch),
    452                     instance->position % instance->cols,
    453                     instance->position / instance->cols, false);
    454                 instance->position++;
    455         }
    456 
    457         if (instance->position >= instance->cols * instance->rows) {
    458                 instance->position -= instance->cols;
    459                 screen_scroll(instance);
    460         }
    461 
     466        if (instance->offset_row >= instance->screen_rows / 2)
     467                instance->offset_row -= instance->screen_rows / 2;
     468        else
     469                instance->offset_row = 0;
     470
     471        fb_redraw_internal(instance);
    462472        cursor_put(instance);
    463473
     
    465475}
    466476
    467 /** Scroll the framebuffer up
    468  *
    469  */
    470 static void fb_scroll_up(outdev_t *dev)
     477/** Scroll the framebuffer down
     478 *
     479 */
     480static void fb_scroll_down(outdev_t *dev)
    471481{
    472482        fb_instance_t *instance = (fb_instance_t *) dev->data;
    473483        spinlock_lock(&instance->lock);
    474484
    475         if (instance->offset_row >= instance->rowtrim / 2)
    476                 instance->offset_row -= instance->rowtrim / 2;
     485        if (instance->offset_row + instance->screen_rows / 2 <=
     486            instance->rows - instance->screen_rows)
     487                instance->offset_row += instance->screen_rows / 2;
    477488        else
    478                 instance->offset_row = 0;
    479 
    480         fb_redraw_internal(instance);
    481         cursor_put(instance);
    482 
    483         spinlock_unlock(&instance->lock);
    484 }
    485 
    486 /** Scroll the framebuffer down
    487  *
    488  */
    489 static void fb_scroll_down(outdev_t *dev)
    490 {
    491         fb_instance_t *instance = (fb_instance_t *) dev->data;
    492         spinlock_lock(&instance->lock);
    493 
    494         if (instance->offset_row + instance->rowtrim / 2 <=
    495             instance->rows - instance->rowtrim)
    496                 instance->offset_row += instance->rowtrim / 2;
    497         else
    498                 instance->offset_row = instance->rows - instance->rowtrim;
     489                instance->offset_row = instance->rows - instance->screen_rows;
    499490
    500491        fb_redraw_internal(instance);
     
    615606        instance->scanline = props->scan;
    616607
    617         instance->rowtrim = Y2ROW(instance->yres);
     608        instance->screen_rows = Y2ROW(instance->yres);
    618609
    619610        instance->cols = X2COL(instance->xres);
    620         instance->rows = FB_PAGES * instance->rowtrim;
    621 
    622         instance->start_row = instance->rows - instance->rowtrim;
     611        instance->rows = FB_PAGES * instance->screen_rows;
     612
     613        instance->start_row = instance->rows - instance->screen_rows;
    623614        instance->offset_row = instance->start_row;
    624         instance->position = instance->start_row * instance->cols;
     615        instance->row = instance->start_row;
     616        instance->column = 0;
    625617
    626618        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
Note: See TracChangeset for help on using the changeset viewer.