Changeset 888c06e in mainline


Ignore:
Timestamp:
2025-04-17T16:13:24Z (5 days ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
61c91532, eb2187c4
Parents:
c4cfe4c
Message:

Avoid using general division and modulo ops in framebuffer

These can be very expensive and slow on CPUs without a hardware
divider, and sometimes even on those that have it.

File:
1 edited

Legend:

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

    rc4cfe4c 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;
     
    124126        /** Partial character between writes */
    125127        mbstate_t mbstate;
     128
     129        unsigned int row;
     130        unsigned int column;
    126131} fb_instance_t;
    127132
     
    250255
    251256        unsigned int rel_row = row - instance->offset_row;
    252         if (rel_row >= instance->rowtrim)
     257        if (rel_row >= instance->screen_rows)
    253258                return;
    254259
     
    262267}
    263268
    264 /** Scroll screen down by one row
    265  *
    266  */
    267 static void screen_scroll(fb_instance_t *instance)
    268 {
    269         if ((!instance->parea.mapped) || (console_override)) {
    270                 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
    271                         unsigned int y = ROW2Y(rel_row);
    272                         unsigned int row = rel_row + instance->offset_row;
    273 
    274                         for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
    275                                 unsigned int x;
    276                                 unsigned int col;
    277                                 size_t bb_pos = BB_POS(instance, 0, row);
    278                                 size_t bb_pos1 = BB_POS(instance, 0, row + 1);
    279 
    280                                 for (col = 0, x = 0; col < instance->cols;
    281                                     col++, x += FONT_WIDTH) {
    282                                         uint16_t glyph;
    283 
    284                                         if (row < instance->rows - 1) {
    285                                                 if (instance->backbuf[bb_pos] ==
    286                                                     instance->backbuf[bb_pos1])
    287                                                         goto skip;
    288 
    289                                                 glyph = instance->backbuf[bb_pos1];
    290                                         } else
    291                                                 glyph = 0;
    292 
    293                                         memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
    294                                             &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
    295                                             instance->glyphscanline);
    296                                 skip:
    297                                         BB_NEXT_COL(bb_pos);
    298                                         BB_NEXT_COL(bb_pos1);
    299                                 }
    300                         }
    301                 }
    302         }
    303 
    304         /*
    305          * Implement backbuffer scrolling by wrapping around
    306          * the cyclic buffer.
    307          */
    308 
    309         instance->start_row++;
    310         if (instance->start_row == instance->rows)
    311                 instance->start_row = 0;
    312 
    313         memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
    314             instance->cols, 0);
    315 }
    316 
    317269static void cursor_put(fb_instance_t *instance)
    318270{
    319         unsigned int col = instance->position % instance->cols;
    320         unsigned int row = instance->position / instance->cols;
     271        unsigned int col = instance->column;
     272        unsigned int row = instance->row;
    321273
    322274        glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
     
    325277static void cursor_remove(fb_instance_t *instance)
    326278{
    327         unsigned int col = instance->position % instance->cols;
    328         unsigned int row = instance->position / instance->cols;
     279        unsigned int col = instance->column;
     280        unsigned int row = instance->row;
    329281
    330282        glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
     
    376328static void fb_redraw_internal(fb_instance_t *instance)
    377329{
    378         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++) {
    379331                unsigned int y = ROW2Y(rel_row);
    380332                unsigned int row = rel_row + instance->offset_row;
     
    407359        }
    408360
    409         if (ROW2Y(instance->rowtrim) < instance->yres) {
     361        if (ROW2Y(instance->screen_rows) < instance->yres) {
    410362                unsigned int y;
    411363
    412                 for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
     364                for (y = ROW2Y(instance->screen_rows); y < instance->yres; y++)
    413365                        memcpy(&instance->addr[FB_POS(instance, 0, y)],
    414366                            instance->bgscan, instance->bgscanbytes);
     
    416368}
    417369
     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
    418402/** Print character to screen
    419403 *
     
    425409        switch (ch) {
    426410        case '\n':
    427                 instance->position += instance->cols;
    428                 instance->position -= instance->position % instance->cols;
     411                _advance_row(instance);
    429412                break;
    430413        case '\r':
    431                 instance->position -= instance->position % instance->cols;
     414                instance->column = 0;
    432415                break;
    433416        case '\b':
    434                 if (instance->position % instance->cols)
    435                         instance->position--;
     417                if (instance->column > 0)
     418                        instance->column--;
    436419                break;
    437420        case '\t':
    438421                do {
    439422                        glyph_draw(instance, fb_font_glyph(' '),
    440                             instance->position % instance->cols,
    441                             instance->position / instance->cols, false);
    442                         instance->position++;
    443                 } while (((instance->position % instance->cols) % 8 != 0) &&
    444                     (instance->position < instance->cols * instance->rows));
     423                            instance->column,
     424                            instance->row, false);
     425                        _advance_column(instance);
     426                } while (instance->column % TAB_WIDTH != 0);
    445427                break;
    446428        default:
    447429                glyph_draw(instance, fb_font_glyph(ch),
    448                     instance->position % instance->cols,
    449                     instance->position / instance->cols, false);
    450                 instance->position++;
    451         }
    452 
    453         if (instance->position >= instance->cols * instance->rows) {
    454                 instance->position -= instance->cols;
     430                    instance->column,
     431                    instance->row, false);
     432                _advance_column(instance);
     433        }
     434
     435        while (instance->row >= instance->rows) {
     436                instance->row--;
    455437                screen_scroll(instance);
    456438        }
     
    482464        spinlock_lock(&instance->lock);
    483465
    484         if (instance->offset_row >= instance->rowtrim / 2)
    485                 instance->offset_row -= instance->rowtrim / 2;
     466        if (instance->offset_row >= instance->screen_rows / 2)
     467                instance->offset_row -= instance->screen_rows / 2;
    486468        else
    487469                instance->offset_row = 0;
     
    501483        spinlock_lock(&instance->lock);
    502484
    503         if (instance->offset_row + instance->rowtrim / 2 <=
    504             instance->rows - instance->rowtrim)
    505                 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;
    506488        else
    507                 instance->offset_row = instance->rows - instance->rowtrim;
     489                instance->offset_row = instance->rows - instance->screen_rows;
    508490
    509491        fb_redraw_internal(instance);
     
    624606        instance->scanline = props->scan;
    625607
    626         instance->rowtrim = Y2ROW(instance->yres);
     608        instance->screen_rows = Y2ROW(instance->yres);
    627609
    628610        instance->cols = X2COL(instance->xres);
    629         instance->rows = FB_PAGES * instance->rowtrim;
    630 
    631         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;
    632614        instance->offset_row = instance->start_row;
    633         instance->position = instance->start_row * instance->cols;
     615        instance->row = instance->start_row;
     616        instance->column = 0;
    634617
    635618        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
Note: See TracChangeset for help on using the changeset viewer.