Ignore:
File:
1 edited

Legend:

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

    r7ddc2c7 rf061e404  
    3535
    3636#include <genarch/fb/font-8x16.h>
     37#include <genarch/fb/logo-196x66.h>
    3738#include <genarch/fb/fb.h>
    3839#include <console/chardev.h>
     
    5253#include <byteorder.h>
    5354
    54 #define BG_COLOR     0x001620
    55 #define FG_COLOR     0xf3cf65
     55#define BG_COLOR     0x000080
     56#define FG_COLOR     0xffff00
    5657#define INV_COLOR    0xaaaaaa
    57 
    58 #define FB_PAGES  8
    5958
    6059#define RED(x, bits)    (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
     
    7271
    7372#define BB_POS(instance, col, row) \
    74         ((((instance)->start_row + (row)) % (instance)->rows) * \
    75             (instance)->cols + (col))
     73        ((row) * (instance)->cols + (col))
    7674
    7775#define GLYPH_POS(instance, glyph, y) \
     
    9593        unsigned int yres;
    9694       
    97         /** Number of rows that fit on framebuffer */
     95        unsigned int ylogo;
     96        unsigned int ytrim;
    9897        unsigned int rowtrim;
    9998       
     
    105104        unsigned int bgscanbytes;
    106105       
    107         /** Number of columns in the backbuffer */
    108106        unsigned int cols;
    109         /** Number of rows in the backbuffer */
    110107        unsigned int rows;
    111108       
    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 */
    119109        unsigned int position;
    120110} fb_instance_t;
    121111
    122 static void fb_putchar(outdev_t *, wchar_t);
    123 static void fb_redraw(outdev_t *);
    124 static void fb_scroll_up(outdev_t *);
    125 static void fb_scroll_down(outdev_t *);
     112static void fb_putchar(outdev_t *dev, wchar_t ch);
     113static void fb_redraw_internal(fb_instance_t *instance);
     114static void fb_redraw(outdev_t *dev);
    126115
    127116static outdev_operations_t fbdev_ops = {
    128117        .write = fb_putchar,
    129         .redraw = fb_redraw,
    130         .scroll_up = fb_scroll_up,
    131         .scroll_down = fb_scroll_down
     118        .redraw = fb_redraw
    132119};
    133120
     
    226213}
    227214
     215/** Hide logo and refresh screen
     216 *
     217 */
     218static 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       
    234241        if (!overlay)
    235242                instance->backbuf[BB_POS(instance, col, row)] = glyph;
    236243       
    237         /* Do not output if the framebuffer is used by user space */
    238         if ((instance->parea.mapped) && (!console_override))
     244        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 */
     256static void screen_scroll(fb_instance_t *instance)
     257{
     258        if (instance->ylogo > 0) {
     259                logo_hide(instance);
    239260                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  */
    261 static void screen_scroll(fb_instance_t *instance)
    262 {
     261        }
     262       
    263263        if ((!instance->parea.mapped) || (console_override)) {
    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;
     264                unsigned int row;
     265               
     266                for (row = 0; row < instance->rows; row++) {
     267                        unsigned int y = ROW2Y(row);
     268                        unsigned int yd;
    267269                       
    268                         for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
     270                        for (yd = 0; yd < FONT_SCANLINES; yd++) {
    269271                                unsigned int x;
    270272                                unsigned int col;
     
    291293        }
    292294       
    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        
     295        memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)],
     296            instance->cols * (instance->rows - 1) * sizeof(uint16_t));
    302297        memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
    303298            instance->cols, 0);
     
    363358}
    364359
     360/** Print character to screen
     361 *
     362 * Emulate basic terminal commands.
     363 *
     364 */
     365static 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
    365412static void fb_redraw_internal(fb_instance_t *instance)
    366413{
    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;
    370                
    371                 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
     414        if (instance->ylogo > 0) {
     415                unsigned int y;
     416               
     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++) {
    372435                        unsigned int x;
    373436                        unsigned int col;
     
    389452                    (instance->xres - COL2X(instance->cols)) * instance->pixelbytes;
    390453               
    391                 for (y = 0; y < instance->yres; y++)
     454                for (y = instance->ylogo; y < instance->yres; y++)
    392455                        memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)],
    393456                            instance->bgscan, size);
    394457        }
    395458       
    396         if (ROW2Y(instance->rowtrim) < instance->yres) {
     459        if (ROW2Y(instance->rowtrim) + instance->ylogo < instance->yres) {
    397460                unsigned int y;
    398461               
    399                 for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
     462                for (y = ROW2Y(instance->rowtrim) + instance->ylogo;
     463                    y < instance->yres; y++)
    400464                        memcpy(&instance->addr[FB_POS(instance, 0, y)],
    401465                            instance->bgscan, instance->bgscanbytes);
    402466        }
    403 }
    404 
    405 /** Print character to screen
    406  *
    407  * Emulate basic terminal commands.
    408  *
    409  */
    410 static 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  */
    460 static 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  */
    479 static 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);
    494467}
    495468
     
    589562        instance->yres = props->y;
    590563        instance->scanline = props->scan;
    591        
    592         instance->rowtrim = Y2ROW(instance->yres);
     564        instance->position = 0;
    593565       
    594566        instance->cols = X2COL(instance->xres);
    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;
     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        }
    600580       
    601581        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
Note: See TracChangeset for help on using the changeset viewer.