Changeset 7ddc2c7 in mainline for kernel/genarch/src/fb/fb.c


Ignore:
Timestamp:
2014-03-17T15:00:13Z (10 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9df6b0f
Parents:
e1fc679a
Message:

add support for framebuffer history paging (using Page Up and Page Down keys), inspiration taken from the code by Sebastian Köln
add support for input device out-of-band signalling

File:
1 edited

Legend:

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

    re1fc679a r7ddc2c7  
    5656#define INV_COLOR    0xaaaaaa
    5757
     58#define FB_PAGES  8
     59
    5860#define RED(x, bits)    (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
    5961#define GREEN(x, bits)  (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
     
    7072
    7173#define BB_POS(instance, col, row) \
    72         ((row) * (instance)->cols + (col))
     74        ((((instance)->start_row + (row)) % (instance)->rows) * \
     75            (instance)->cols + (col))
    7376
    7477#define GLYPH_POS(instance, glyph, y) \
     
    9295        unsigned int yres;
    9396       
     97        /** Number of rows that fit on framebuffer */
    9498        unsigned int rowtrim;
    9599       
     
    101105        unsigned int bgscanbytes;
    102106       
     107        /** Number of columns in the backbuffer */
    103108        unsigned int cols;
     109        /** Number of rows in the backbuffer */
    104110        unsigned int rows;
    105111       
     112        /** Starting row in the cyclic backbuffer */
     113        unsigned int start_row;
     114       
     115        /** Top-most visible row (relative to start_row) */
     116        unsigned int offset_row;
     117       
     118        /** Current backbuffer position */
    106119        unsigned int position;
    107120} fb_instance_t;
    108121
    109 static void fb_putchar(outdev_t *dev, wchar_t ch);
    110 static void fb_redraw_internal(fb_instance_t *instance);
    111 static void fb_redraw(outdev_t *dev);
     122static void fb_putchar(outdev_t *, wchar_t);
     123static void fb_redraw(outdev_t *);
     124static void fb_scroll_up(outdev_t *);
     125static void fb_scroll_down(outdev_t *);
    112126
    113127static outdev_operations_t fbdev_ops = {
    114128        .write = fb_putchar,
    115         .redraw = fb_redraw
     129        .redraw = fb_redraw,
     130        .scroll_up = fb_scroll_up,
     131        .scroll_down = fb_scroll_down
    116132};
    117133
     
    216232    unsigned int col, unsigned int row, bool overlay)
    217233{
    218         unsigned int x = COL2X(col);
    219         unsigned int y = ROW2Y(row);
    220         unsigned int yd;
    221        
    222234        if (!overlay)
    223235                instance->backbuf[BB_POS(instance, col, row)] = glyph;
    224236       
     237        /* Do not output if the framebuffer is used by user space */
     238        if ((instance->parea.mapped) && (!console_override))
     239                return;
     240       
     241        /* Check whether the glyph should be visible */
     242        if (row < instance->offset_row)
     243                return;
     244       
     245        unsigned int rel_row = row - instance->offset_row;
     246        if (rel_row >= instance->rowtrim)
     247                return;
     248       
     249        unsigned int x = COL2X(col);
     250        unsigned int y = ROW2Y(rel_row);
     251       
     252        for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++)
     253                memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
     254                    &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
     255                    instance->glyphscanline);
     256}
     257
     258/** Scroll screen down by one row
     259 *
     260 */
     261static void screen_scroll(fb_instance_t *instance)
     262{
    225263        if ((!instance->parea.mapped) || (console_override)) {
    226                 for (yd = 0; yd < FONT_SCANLINES; yd++)
    227                         memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
    228                             &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
    229                             instance->glyphscanline);
    230         }
    231 }
    232 
    233 /** Scroll screen down by one row
    234  *
    235  *
    236  */
    237 static void screen_scroll(fb_instance_t *instance)
    238 {
    239         if ((!instance->parea.mapped) || (console_override)) {
    240                 unsigned int row;
    241                
    242                 for (row = 0; row < instance->rows; row++) {
    243                         unsigned int y = ROW2Y(row);
    244                         unsigned int yd;
     264                for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
     265                        unsigned int y = ROW2Y(rel_row);
     266                        unsigned int row = rel_row + instance->offset_row;
    245267                       
    246                         for (yd = 0; yd < FONT_SCANLINES; yd++) {
     268                        for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
    247269                                unsigned int x;
    248270                                unsigned int col;
     
    269291        }
    270292       
    271         memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)],
    272             instance->cols * (instance->rows - 1) * sizeof(uint16_t));
     293        /*
     294         * Implement backbuffer scrolling by wrapping around
     295         * the cyclic buffer.
     296         */
     297       
     298        instance->start_row++;
     299        if (instance->start_row == instance->rows)
     300                instance->start_row = 0;
     301       
    273302        memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
    274303            instance->cols, 0);
     
    334363}
    335364
    336 /** Print character to screen
    337  *
    338  * Emulate basic terminal commands.
    339  *
    340  */
    341 static void fb_putchar(outdev_t *dev, wchar_t ch)
    342 {
    343         fb_instance_t *instance = (fb_instance_t *) dev->data;
    344         spinlock_lock(&instance->lock);
    345        
    346         switch (ch) {
    347         case '\n':
    348                 cursor_remove(instance);
    349                 instance->position += instance->cols;
    350                 instance->position -= instance->position % instance->cols;
    351                 break;
    352         case '\r':
    353                 cursor_remove(instance);
    354                 instance->position -= instance->position % instance->cols;
    355                 break;
    356         case '\b':
    357                 cursor_remove(instance);
    358                 if (instance->position % instance->cols)
    359                         instance->position--;
    360                 break;
    361         case '\t':
    362                 cursor_remove(instance);
    363                 do {
    364                         glyph_draw(instance, fb_font_glyph(' '),
    365                             instance->position % instance->cols,
    366                             instance->position / instance->cols, false);
    367                         instance->position++;
    368                 } while (((instance->position % instance->cols) % 8 != 0) &&
    369                     (instance->position < instance->cols * instance->rows));
    370                 break;
    371         default:
    372                 glyph_draw(instance, fb_font_glyph(ch),
    373                     instance->position % instance->cols,
    374                     instance->position / instance->cols, false);
    375                 instance->position++;
    376         }
    377        
    378         if (instance->position >= instance->cols * instance->rows) {
    379                 instance->position -= instance->cols;
    380                 screen_scroll(instance);
    381         }
    382        
    383         cursor_put(instance);
    384        
    385         spinlock_unlock(&instance->lock);
    386 }
    387 
    388365static void fb_redraw_internal(fb_instance_t *instance)
    389366{
    390         unsigned int row;
    391        
    392         for (row = 0; row < instance->rowtrim; row++) {
    393                 unsigned int y = ROW2Y(row);
    394                 unsigned int yd;
     367        for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
     368                unsigned int y = ROW2Y(rel_row);
     369                unsigned int row = rel_row + instance->offset_row;
    395370               
    396                 for (yd = 0; yd < FONT_SCANLINES; yd++) {
     371                for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
    397372                        unsigned int x;
    398373                        unsigned int col;
     
    428403}
    429404
     405/** Print character to screen
     406 *
     407 * Emulate basic terminal commands.
     408 *
     409 */
     410static void fb_putchar(outdev_t *dev, wchar_t ch)
     411{
     412        fb_instance_t *instance = (fb_instance_t *) dev->data;
     413        spinlock_lock(&instance->lock);
     414       
     415        switch (ch) {
     416        case '\n':
     417                cursor_remove(instance);
     418                instance->position += instance->cols;
     419                instance->position -= instance->position % instance->cols;
     420                break;
     421        case '\r':
     422                cursor_remove(instance);
     423                instance->position -= instance->position % instance->cols;
     424                break;
     425        case '\b':
     426                cursor_remove(instance);
     427                if (instance->position % instance->cols)
     428                        instance->position--;
     429                break;
     430        case '\t':
     431                cursor_remove(instance);
     432                do {
     433                        glyph_draw(instance, fb_font_glyph(' '),
     434                            instance->position % instance->cols,
     435                            instance->position / instance->cols, false);
     436                        instance->position++;
     437                } while (((instance->position % instance->cols) % 8 != 0) &&
     438                    (instance->position < instance->cols * instance->rows));
     439                break;
     440        default:
     441                glyph_draw(instance, fb_font_glyph(ch),
     442                    instance->position % instance->cols,
     443                    instance->position / instance->cols, false);
     444                instance->position++;
     445        }
     446       
     447        if (instance->position >= instance->cols * instance->rows) {
     448                instance->position -= instance->cols;
     449                screen_scroll(instance);
     450        }
     451       
     452        cursor_put(instance);
     453       
     454        spinlock_unlock(&instance->lock);
     455}
     456
     457/** Scroll the framebuffer up
     458 *
     459 */
     460static void fb_scroll_up(outdev_t *dev)
     461{
     462        fb_instance_t *instance = (fb_instance_t *) dev->data;
     463        spinlock_lock(&instance->lock);
     464       
     465        if (instance->offset_row >= instance->rowtrim / 2)
     466                instance->offset_row -= instance->rowtrim / 2;
     467        else
     468                instance->offset_row = 0;
     469       
     470        fb_redraw_internal(instance);
     471        cursor_put(instance);
     472       
     473        spinlock_unlock(&instance->lock);
     474}
     475
     476/** Scroll the framebuffer down
     477 *
     478 */
     479static void fb_scroll_down(outdev_t *dev)
     480{
     481        fb_instance_t *instance = (fb_instance_t *) dev->data;
     482        spinlock_lock(&instance->lock);
     483       
     484        if (instance->offset_row + instance->rowtrim / 2 <=
     485            instance->rows - instance->rowtrim)
     486                instance->offset_row += instance->rowtrim / 2;
     487        else
     488                instance->offset_row = instance->rows - instance->rowtrim;
     489       
     490        fb_redraw_internal(instance);
     491        cursor_put(instance);
     492       
     493        spinlock_unlock(&instance->lock);
     494}
     495
    430496/** Refresh the screen
    431497 *
     
    523589        instance->yres = props->y;
    524590        instance->scanline = props->scan;
    525         instance->position = 0;
     591       
     592        instance->rowtrim = Y2ROW(instance->yres);
    526593       
    527594        instance->cols = X2COL(instance->xres);
    528         instance->rows = Y2ROW(instance->yres);
    529        
    530         instance->rowtrim = instance->rows;
     595        instance->rows = FB_PAGES * instance->rowtrim;
     596       
     597        instance->start_row = instance->rows - instance->rowtrim;
     598        instance->offset_row = instance->start_row;
     599        instance->position = instance->start_row * instance->cols;
    531600       
    532601        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
Note: See TracChangeset for help on using the changeset viewer.