Ignore:
File:
1 edited

Legend:

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

    rf061e404 r7ddc2c7  
    3535
    3636#include <genarch/fb/font-8x16.h>
    37 #include <genarch/fb/logo-196x66.h>
    3837#include <genarch/fb/fb.h>
    3938#include <console/chardev.h>
     
    5352#include <byteorder.h>
    5453
    55 #define BG_COLOR     0x000080
    56 #define FG_COLOR     0xffff00
     54#define BG_COLOR     0x001620
     55#define FG_COLOR     0xf3cf65
    5756#define INV_COLOR    0xaaaaaa
     57
     58#define FB_PAGES  8
    5859
    5960#define RED(x, bits)    (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
     
    7172
    7273#define BB_POS(instance, col, row) \
    73         ((row) * (instance)->cols + (col))
     74        ((((instance)->start_row + (row)) % (instance)->rows) * \
     75            (instance)->cols + (col))
    7476
    7577#define GLYPH_POS(instance, glyph, y) \
     
    9395        unsigned int yres;
    9496       
    95         unsigned int ylogo;
    96         unsigned int ytrim;
     97        /** Number of rows that fit on framebuffer */
    9798        unsigned int rowtrim;
    9899       
     
    104105        unsigned int bgscanbytes;
    105106       
     107        /** Number of columns in the backbuffer */
    106108        unsigned int cols;
     109        /** Number of rows in the backbuffer */
    107110        unsigned int rows;
    108111       
     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 */
    109119        unsigned int position;
    110120} fb_instance_t;
    111121
    112 static void fb_putchar(outdev_t *dev, wchar_t ch);
    113 static void fb_redraw_internal(fb_instance_t *instance);
    114 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 *);
    115126
    116127static outdev_operations_t fbdev_ops = {
    117128        .write = fb_putchar,
    118         .redraw = fb_redraw
     129        .redraw = fb_redraw,
     130        .scroll_up = fb_scroll_up,
     131        .scroll_down = fb_scroll_down
    119132};
    120133
     
    213226}
    214227
    215 /** Hide logo and refresh screen
    216  *
    217  */
    218 static void logo_hide(fb_instance_t *instance)
    219 {
    220         instance->ylogo = 0;
    221         instance->ytrim = instance->yres;
    222         instance->rowtrim = instance->rows;
    223        
    224         if ((!instance->parea.mapped) || (console_override))
    225                 fb_redraw_internal(instance);
    226 }
    227 
    228228/** Draw character at given position
    229229 *
     
    232232    unsigned int col, unsigned int row, bool overlay)
    233233{
    234         unsigned int x = COL2X(col);
    235         unsigned int y = ROW2Y(row);
    236         unsigned int yd;
    237        
    238         if (y >= instance->ytrim)
    239                 logo_hide(instance);
    240        
    241234        if (!overlay)
    242235                instance->backbuf[BB_POS(instance, col, row)] = glyph;
    243236       
     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{
    244263        if ((!instance->parea.mapped) || (console_override)) {
    245                 for (yd = 0; yd < FONT_SCANLINES; yd++)
    246                         memcpy(&instance->addr[FB_POS(instance, x, y + yd + instance->ylogo)],
    247                             &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
    248                             instance->glyphscanline);
    249         }
    250 }
    251 
    252 /** Scroll screen down by one row
    253  *
    254  *
    255  */
    256 static void screen_scroll(fb_instance_t *instance)
    257 {
    258         if (instance->ylogo > 0) {
    259                 logo_hide(instance);
    260                 return;
    261         }
    262        
    263         if ((!instance->parea.mapped) || (console_override)) {
    264                 unsigned int row;
    265                
    266                 for (row = 0; row < instance->rows; row++) {
    267                         unsigned int y = ROW2Y(row);
    268                         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;
    269267                       
    270                         for (yd = 0; yd < FONT_SCANLINES; yd++) {
     268                        for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
    271269                                unsigned int x;
    272270                                unsigned int col;
     
    293291        }
    294292       
    295         memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)],
    296             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       
    297302        memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
    298303            instance->cols, 0);
     
    358363}
    359364
    360 /** Print character to screen
    361  *
    362  * Emulate basic terminal commands.
    363  *
    364  */
    365 static void fb_putchar(outdev_t *dev, wchar_t ch)
    366 {
    367         fb_instance_t *instance = (fb_instance_t *) dev->data;
    368         spinlock_lock(&instance->lock);
    369        
    370         switch (ch) {
    371         case '\n':
    372                 cursor_remove(instance);
    373                 instance->position += instance->cols;
    374                 instance->position -= instance->position % instance->cols;
    375                 break;
    376         case '\r':
    377                 cursor_remove(instance);
    378                 instance->position -= instance->position % instance->cols;
    379                 break;
    380         case '\b':
    381                 cursor_remove(instance);
    382                 if (instance->position % instance->cols)
    383                         instance->position--;
    384                 break;
    385         case '\t':
    386                 cursor_remove(instance);
    387                 do {
    388                         glyph_draw(instance, fb_font_glyph(' '),
    389                             instance->position % instance->cols,
    390                             instance->position / instance->cols, false);
    391                         instance->position++;
    392                 } while (((instance->position % instance->cols) % 8 != 0) &&
    393                     (instance->position < instance->cols * instance->rows));
    394                 break;
    395         default:
    396                 glyph_draw(instance, fb_font_glyph(ch),
    397                     instance->position % instance->cols,
    398                     instance->position / instance->cols, false);
    399                 instance->position++;
    400         }
    401        
    402         if (instance->position >= instance->cols * instance->rows) {
    403                 instance->position -= instance->cols;
    404                 screen_scroll(instance);
    405         }
    406        
    407         cursor_put(instance);
    408        
    409         spinlock_unlock(&instance->lock);
    410 }
    411 
    412365static void fb_redraw_internal(fb_instance_t *instance)
    413366{
    414         if (instance->ylogo > 0) {
    415                 unsigned int y;
     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;
    416370               
    417                 for (y = 0; y < LOGO_HEIGHT; y++) {
    418                         unsigned int x;
    419                        
    420                         for (x = 0; x < instance->xres; x++)
    421                                 instance->rgb_conv(&instance->addr[FB_POS(instance, x, y)],
    422                                     (x < LOGO_WIDTH) ?
    423                                     fb_logo[y * LOGO_WIDTH + x] :
    424                                     LOGO_COLOR);
    425                 }
    426         }
    427        
    428         unsigned int row;
    429        
    430         for (row = 0; row < instance->rowtrim; row++) {
    431                 unsigned int y = instance->ylogo + ROW2Y(row);
    432                 unsigned int yd;
    433                
    434                 for (yd = 0; yd < FONT_SCANLINES; yd++) {
     371                for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
    435372                        unsigned int x;
    436373                        unsigned int col;
     
    452389                    (instance->xres - COL2X(instance->cols)) * instance->pixelbytes;
    453390               
    454                 for (y = instance->ylogo; y < instance->yres; y++)
     391                for (y = 0; y < instance->yres; y++)
    455392                        memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)],
    456393                            instance->bgscan, size);
    457394        }
    458395       
    459         if (ROW2Y(instance->rowtrim) + instance->ylogo < instance->yres) {
     396        if (ROW2Y(instance->rowtrim) < instance->yres) {
    460397                unsigned int y;
    461398               
    462                 for (y = ROW2Y(instance->rowtrim) + instance->ylogo;
    463                     y < instance->yres; y++)
     399                for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
    464400                        memcpy(&instance->addr[FB_POS(instance, 0, y)],
    465401                            instance->bgscan, instance->bgscanbytes);
    466402        }
     403}
     404
     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);
    467494}
    468495
     
    562589        instance->yres = props->y;
    563590        instance->scanline = props->scan;
    564         instance->position = 0;
     591       
     592        instance->rowtrim = Y2ROW(instance->yres);
    565593       
    566594        instance->cols = X2COL(instance->xres);
    567         instance->rows = Y2ROW(instance->yres);
    568        
    569         if (instance->yres > LOGO_HEIGHT) {
    570                 instance->ylogo = LOGO_HEIGHT;
    571                 instance->rowtrim = instance->rows - Y2ROW(instance->ylogo);
    572                 if (instance->ylogo % FONT_SCANLINES > 0)
    573                         instance->rowtrim--;
    574                 instance->ytrim = ROW2Y(instance->rowtrim);
    575         } else {
    576                 instance->ylogo = 0;
    577                 instance->ytrim = instance->yres;
    578                 instance->rowtrim = instance->rows;
    579         }
     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;
    580600       
    581601        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
Note: See TracChangeset for help on using the changeset viewer.