Ignore:
File:
1 edited

Legend:

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

    re037cf37 reb2187c4  
    4545#include <align.h>
    4646#include <panic.h>
    47 #include <mem.h>
     47#include <memw.h>
    4848#include <config.h>
    4949#include <bitops.h>
     
    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
     
    265273{
    266274        if ((!instance->parea.mapped) || (console_override)) {
    267                 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
     275                for (unsigned int rel_row = 0; rel_row < instance->screen_rows; rel_row++) {
    268276                        unsigned int y = ROW2Y(rel_row);
    269277                        unsigned int row = rel_row + instance->offset_row;
     
    314322static void cursor_put(fb_instance_t *instance)
    315323{
    316         unsigned int col = instance->position % instance->cols;
    317         unsigned int row = instance->position / instance->cols;
     324        unsigned int col = instance->column;
     325        unsigned int row = instance->row;
    318326
    319327        glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
     
    322330static void cursor_remove(fb_instance_t *instance)
    323331{
    324         unsigned int col = instance->position % instance->cols;
    325         unsigned int row = instance->position / instance->cols;
     332        unsigned int col = instance->column;
     333        unsigned int row = instance->row;
    326334
    327335        glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
     
    373381static void fb_redraw_internal(fb_instance_t *instance)
    374382{
    375         for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) {
     383        for (unsigned int rel_row = 0; rel_row < instance->screen_rows; rel_row++) {
    376384                unsigned int y = ROW2Y(rel_row);
    377385                unsigned int row = rel_row + instance->offset_row;
     
    404412        }
    405413
    406         if (ROW2Y(instance->rowtrim) < instance->yres) {
     414        if (ROW2Y(instance->screen_rows) < instance->yres) {
    407415                unsigned int y;
    408416
    409                 for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++)
     417                for (y = ROW2Y(instance->screen_rows); y < instance->yres; y++)
    410418                        memcpy(&instance->addr[FB_POS(instance, 0, y)],
    411419                            instance->bgscan, instance->bgscanbytes);
     
    413421}
    414422
     423static void _advance_row(fb_instance_t *instance)
     424{
     425        instance->column = 0;
     426        instance->row++;
     427}
     428
     429static void _advance_column(fb_instance_t *instance)
     430{
     431        instance->column++;
     432        if (instance->column == instance->cols)
     433                _advance_row(instance);
     434}
     435
    415436/** Print character to screen
    416437 *
     
    418439 *
    419440 */
    420 static void fb_putuchar(outdev_t *dev, char32_t ch)
     441static void _putuchar(fb_instance_t *instance, char32_t ch)
     442{
     443        switch (ch) {
     444        case '\n':
     445                _advance_row(instance);
     446                break;
     447        case '\r':
     448                instance->column = 0;
     449                break;
     450        case '\b':
     451                if (instance->column > 0)
     452                        instance->column--;
     453                break;
     454        case '\t':
     455                do {
     456                        glyph_draw(instance, fb_font_glyph(' '),
     457                            instance->column,
     458                            instance->row, false);
     459                        _advance_column(instance);
     460                } while (instance->column % TAB_WIDTH != 0);
     461                break;
     462        default:
     463                glyph_draw(instance, fb_font_glyph(ch),
     464                    instance->column,
     465                    instance->row, false);
     466                _advance_column(instance);
     467        }
     468
     469        while (instance->row >= instance->rows) {
     470                instance->row--;
     471                screen_scroll(instance);
     472        }
     473}
     474
     475static void fb_write(outdev_t *dev, const char *s, size_t n)
     476{
     477        fb_instance_t *instance = (fb_instance_t *) dev->data;
     478
     479        spinlock_lock(&instance->lock);
     480        cursor_remove(instance);
     481
     482        size_t offset = 0;
     483        char32_t ch;
     484
     485        while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))
     486                _putuchar(instance, ch);
     487
     488        cursor_put(instance);
     489        spinlock_unlock(&instance->lock);
     490}
     491
     492/** Scroll the framebuffer up
     493 *
     494 */
     495static void fb_scroll_up(outdev_t *dev)
    421496{
    422497        fb_instance_t *instance = (fb_instance_t *) dev->data;
    423498        spinlock_lock(&instance->lock);
    424499
    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 
     500        if (instance->offset_row >= instance->screen_rows / 2)
     501                instance->offset_row -= instance->screen_rows / 2;
     502        else
     503                instance->offset_row = 0;
     504
     505        fb_redraw_internal(instance);
    462506        cursor_put(instance);
    463507
     
    465509}
    466510
    467 /** Scroll the framebuffer up
    468  *
    469  */
    470 static void fb_scroll_up(outdev_t *dev)
     511/** Scroll the framebuffer down
     512 *
     513 */
     514static void fb_scroll_down(outdev_t *dev)
    471515{
    472516        fb_instance_t *instance = (fb_instance_t *) dev->data;
    473517        spinlock_lock(&instance->lock);
    474518
    475         if (instance->offset_row >= instance->rowtrim / 2)
    476                 instance->offset_row -= instance->rowtrim / 2;
     519        if (instance->offset_row + instance->screen_rows / 2 <=
     520            instance->rows - instance->screen_rows)
     521                instance->offset_row += instance->screen_rows / 2;
    477522        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;
     523                instance->offset_row = instance->rows - instance->screen_rows;
    499524
    500525        fb_redraw_internal(instance);
     
    615640        instance->scanline = props->scan;
    616641
    617         instance->rowtrim = Y2ROW(instance->yres);
     642        instance->screen_rows = Y2ROW(instance->yres);
    618643
    619644        instance->cols = X2COL(instance->xres);
    620         instance->rows = FB_PAGES * instance->rowtrim;
    621 
    622         instance->start_row = instance->rows - instance->rowtrim;
     645        instance->rows = FB_PAGES * instance->screen_rows;
     646
     647        instance->start_row = instance->rows - instance->screen_rows;
    623648        instance->offset_row = instance->start_row;
    624         instance->position = instance->start_row * instance->cols;
     649        instance->row = instance->start_row;
     650        instance->column = 0;
    625651
    626652        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
     
    633659
    634660        instance->addr = (uint8_t *) km_map((uintptr_t) props->addr, fbsize,
    635             KM_NATURAL_ALIGNMENT, PAGE_WRITE | PAGE_NOT_CACHEABLE);
     661            KM_NATURAL_ALIGNMENT, PAGE_WRITE | PAGE_WRITE_COMBINE);
    636662        if (!instance->addr) {
    637663                LOG("Unable to map framebuffer.");
Note: See TracChangeset for help on using the changeset viewer.