Changeset 68a4442 in mainline


Ignore:
Timestamp:
2008-12-26T13:29:49Z (15 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
713e6f2d
Parents:
edf5774
Message:

New fb glyph drawing algorithm, created with color support in mind. Two versions, 'aligned' and 'fallback', more may follow. Glyphs is now a style-independent bit mask. Cursor shape support vanished but will return.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fb/fb.c

    redf5774 r68a4442  
    7272#define MAX_VIEWPORTS    128  /**< Viewport is a rectangular area on the screen */
    7373
     74/** Function to render a pixel from a RGB value. */
    7475typedef void (*rgb_conv_t)(void *, uint32_t);
     76
     77/** Function to draw a glyph. */
     78typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor,
     79    uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color);
    7580
    7681struct {
     
    100105        unsigned int rows;
    101106       
    102         /* Style and glyphs for text printing */
     107        /*
     108         * Style and glyphs for text printing
     109         */
     110
     111        /** Current style. */
    103112        style_t style;
     113
     114        /** Pre-rendered mask for rendering glyphs. Different viewports
     115         * might use different drawing functions depending on whether their
     116         * scanlines are aligned on a word boundary.*/
    104117        uint8_t *glyphs;
     118
    105119        uint8_t *bgpixel;
     120
     121        /** Glyph drawing function for this viewport. */
     122        dg_t dglyph;
    106123       
    107124        /* Auto-cursor position */
     
    140157static bool client_connected = false;  /**< Allow only 1 connection */
    141158
    142 static void draw_glyph(unsigned int x, unsigned int y, bool cursor,
    143     uint8_t *glyphs, uint8_t glyph);
     159static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
     160    uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color);
     161static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,
     162    uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color);
     163
    144164static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
    145165    unsigned int row);
     
    334354                        }
    335355
    336                         draw_glyph(x, y, false, vport->glyphs, glyph);
     356                        (*vport->dglyph)(x, y, false, vport->glyphs, glyph,
     357                            vport->style.fg_color, vport->style.bg_color);
    337358                        x += FONT_WIDTH;
    338359                }
     
    377398                                screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes],
    378399                                    (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x)))
    379                                     ? vport->style.fg_color : vport->style.bg_color);
     400                                    ? 0xffffff : 0x000000);
    380401                               
    381                                 uint32_t curcolor;
    382                                
    383                                 if (y < FONT_SCANLINES - 2)
    384                                         curcolor =
    385                                             (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x)))
    386                                             ? vport->style.fg_color : vport->style.bg_color;
    387                                 else
    388                                         curcolor = vport->style.fg_color;
    389                                
    390                                 screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], curcolor);
     402                                screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes],
     403                                    (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x)))
     404                                    ? 0x000000 : 0xffffff);
    391405                        }
    392406                }
     
    423437        unsigned int bbsize = cols * rows;
    424438        unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes;
     439        unsigned int word_size = sizeof(unsigned long);
    425440       
    426441        uint8_t *backbuf = (uint8_t *) malloc(bbsize);
     
    458473        viewports[i].glyphs = glyphs;
    459474        viewports[i].bgpixel = bgpixel;
    460        
     475
     476        /*
     477         * Conditions necessary  to select aligned version:
     478         *
     479         *   - word size is divisible by pixelbytes
     480         *   - cell scanline size is divisible by word size
     481         *   - cell scanlines are word-aligned
     482         */
     483        if ((word_size % screen.pixelbytes) == 0 &&
     484            (FONT_WIDTH * screen.pixelbytes) % word_size == 0 &&
     485            (x * screen.pixelbytes) % word_size == 0 &&
     486            screen.scanline % word_size == 0) {
     487
     488                viewports[i].dglyph = draw_glyph_aligned;
     489        } else {
     490                viewports[i].dglyph = draw_glyph_fallback;
     491        }
     492
    461493        viewports[i].cur_col = 0;
    462494        viewports[i].cur_row = 0;
     
    535567
    536568
    537 /** Draw a glyph.
    538  *
    539  * @param x      x coordinate of top-left corner on screen.
    540  * @param y      y coordinate of top-left corner on screen.
    541  * @param cursor Draw glyph with cursor
    542  * @param glyphs Pointer to font bitmap.
    543  * @param glyph  Code of the glyph to draw.
    544  *
    545  */
    546 static void draw_glyph(unsigned int x, unsigned int y, bool cursor,
    547     uint8_t *glyphs, uint8_t glyph)
    548 {
    549         unsigned int yd;
    550        
    551         for (yd = 0; yd < FONT_SCANLINES; yd++)
    552                 memcpy(&screen.fb_addr[FB_POS(x, y + yd)],
    553                     &glyphs[GLYPH_POS(glyph, yd, cursor)], screen.glyphscanline);
     569/** Draw a glyph, takes advantage of alignment.
     570 *
     571 * This version can only be used if the following conditions are met:
     572 *
     573 *   - word size is divisible by pixelbytes
     574 *   - cell scanline size is divisible by word size
     575 *   - cell scanlines are word-aligned
     576 *
     577 * It makes use of the pre-rendered mask to process (possibly) several
     578 * pixels at once (word size / pixelbytes pixels at a time are processed)
     579 * making it very fast. Most notably this version is not applicable at 24 bits
     580 * per pixel.
     581 *
     582 * @param x             x coordinate of top-left corner on screen.
     583 * @param y             y coordinate of top-left corner on screen.
     584 * @param cursor        Draw glyph with cursor
     585 * @param glyphs        Pointer to font bitmap.
     586 * @param glyph         Code of the glyph to draw.
     587 * @param fg_color      Foreground color.
     588 * @param bg_color      Backgroudn color.
     589 */
     590static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
     591    uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color)
     592{
     593        unsigned int i, yd;
     594        unsigned long fg_buf, bg_buf;
     595        unsigned long *maskp, *dp;
     596        unsigned long mask;
     597        unsigned int ww, d_add;
     598
     599        /*
     600         * Prepare a pair of words, one filled with foreground-color
     601         * pattern and the other filled with background-color pattern.
     602         */
     603        for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) {
     604                screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes],
     605                    fg_color);
     606                screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes],
     607                    bg_color);
     608        }
     609
     610
     611        /* Pointer to the current position in the mask. */
     612        maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)];
     613
     614        /* Pointer to the current position on the screen. */
     615        dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)];
     616
     617        /* Width of the character cell in words. */
     618        ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long);
     619
     620        /* Offset to add when moving to another screen scanline. */
     621        d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;
     622
     623        for (yd = 0; yd < FONT_SCANLINES; yd++) {
     624                /*
     625                 * Now process the cell scanline, combining foreground
     626                 * and background color patters using the pre-rendered mask.
     627                 */
     628                for (i = 0; i < ww; i++) {
     629                        mask = *maskp++;
     630                        *dp++ = (fg_buf & mask) | (bg_buf & ~mask);
     631                }
     632
     633                /* Move to the beginning of the next scanline of the cell. */
     634                dp = (unsigned long *) ((uint8_t *) dp + d_add);
     635        }
     636}
     637
     638/** Draw a glyph, fallback version.
     639 *
     640 * This version does not make use of the pre-rendered mask, it uses
     641 * the font bitmap directly. It works always, but it is slower.
     642 *
     643 * @param x             x coordinate of top-left corner on screen.
     644 * @param y             y coordinate of top-left corner on screen.
     645 * @param cursor        Draw glyph with cursor
     646 * @param glyphs        Pointer to font bitmap.
     647 * @param glyph         Code of the glyph to draw.
     648 * @param fg_color      Foreground color.
     649 * @param bg_color      Backgroudn color.
     650 */
     651void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,
     652    uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color)
     653{
     654        unsigned int i, j, yd;
     655        uint8_t fg_buf[4], bg_buf[4];
     656        uint8_t *dp, *sp;
     657        unsigned int d_add;
     658        uint8_t b;
     659
     660        /* Pre-render 1x the foreground and background color pixels. */
     661        if (cursor) {
     662                screen.rgb_conv(fg_buf, bg_color);
     663                screen.rgb_conv(bg_buf, fg_color);
     664        } else {
     665                screen.rgb_conv(fg_buf, fg_color);
     666                screen.rgb_conv(bg_buf, bg_color);
     667        }
     668
     669        /* Pointer to the current position on the screen. */
     670        dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)];
     671
     672        /* Offset to add when moving to another screen scanline. */
     673        d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;
     674
     675        for (yd = 0; yd < FONT_SCANLINES; yd++) {
     676                /* Byte containing bits of the glyph scanline. */
     677                b = fb_font[glyph * FONT_SCANLINES + yd];
     678
     679                for (i = 0; i < FONT_WIDTH; i++) {
     680                        /* Choose color based on the current bit. */
     681                        sp = (b & 0x80) ? fg_buf : bg_buf;
     682
     683                        /* Copy the pixel. */
     684                        for (j = 0; j < screen.pixelbytes; j++) {
     685                                *dp++ = *sp++;
     686                        }
     687
     688                        /* Move to the next bit. */
     689                        b = b << 1;
     690                }
     691               
     692                /* Move to the beginning of the next scanline of the cell. */
     693                dp += d_add;
     694        }
    554695}
    555696
     
    570711       
    571712        glyph = vport->backbuf[BB_POS(vport, col, row)];
    572         draw_glyph(x, y, cursor, vport->glyphs, glyph);
    573 }
    574 
     713
     714        (*vport->dglyph)(x, y, cursor, vport->glyphs, glyph,
     715            vport->style.fg_color, vport->style.bg_color);
     716}
    575717
    576718/** Hide cursor if it is shown
     
    13391481                        vport->style.fg_color = IPC_GET_ARG1(call);
    13401482                        vport->style.bg_color = IPC_GET_ARG2(call);
    1341                         render_glyphs(vport);
    13421483                        retval = EOK;
    13431484                        break;
Note: See TracChangeset for help on using the changeset viewer.