fb.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Ondrej Palkovsky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <genarch/fb/font-8x16.h>
00036 #include <genarch/fb/fb.h>
00037 #include <console/chardev.h>
00038 #include <console/console.h>
00039 #include <sysinfo/sysinfo.h>
00040 #include <mm/slab.h>
00041 #include <align.h>
00042 #include <panic.h>
00043 #include <memstr.h>
00044 #include <config.h>
00045 #include <bitops.h>
00046 #include <print.h>
00047 
00048 #include "helenos.xbm"
00049 
00050 SPINLOCK_INITIALIZE(fb_lock);
00051 
00052 static __u8 *fbaddress = NULL;
00053 
00054 static __u8 *blankline = NULL;
00055 static __u8 *dbbuffer = NULL; /* Buffer for fast scrolling console */
00056 static int dboffset;
00057 
00058 static unsigned int xres = 0;
00059 static unsigned int yres = 0;
00060 static unsigned int scanline = 0;
00061 static unsigned int bitspp = 0;
00062 static unsigned int pixelbytes = 0;
00063 
00064 static unsigned int position = 0;
00065 static unsigned int columns = 0;
00066 static unsigned int rows = 0;
00067 
00068 
00069 #define COL_WIDTH       8
00070 #define ROW_BYTES       (scanline * FONT_SCANLINES)
00071 
00072 #define BGCOLOR         0x000080
00073 #define FGCOLOR         0xffff00
00074 #define LOGOCOLOR       0x2020b0
00075 
00076 #define RED(x, bits)    ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
00077 #define GREEN(x, bits)  ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
00078 #define BLUE(x, bits)   ((x >> (8 - bits)) & ((1 << bits) - 1))
00079 
00080 #define POINTPOS(x, y)  ((y) * scanline + (x) * pixelbytes)
00081 
00082 /***************************************************************/
00083 /* Pixel specific fuctions */
00084 
00085 static void (*rgb2scr)(void *, int);
00086 static int (*scr2rgb)(void *);
00087 
00088 /* Conversion routines between different color representations */
00089 static void rgb_4byte(void *dst, int rgb)
00090 {
00091         *(int *)dst = rgb;
00092 }
00093 
00094 static int byte4_rgb(void *src)
00095 {
00096         return (*(int *)src) & 0xffffff;
00097 }
00098 
00099 static void rgb_3byte(void *dst, int rgb)
00100 {
00101         __u8 *scr = dst;
00102 #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
00103         scr[0] = RED(rgb, 8);
00104         scr[1] = GREEN(rgb, 8);
00105         scr[2] = BLUE(rgb, 8);
00106 #else
00107         scr[2] = RED(rgb, 8);
00108         scr[1] = GREEN(rgb, 8);
00109         scr[0] = BLUE(rgb, 8);
00110 #endif
00111 }
00112 
00113 static int byte3_rgb(void *src)
00114 {
00115         __u8 *scr = src;
00116 #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
00117         return scr[0] << 16 | scr[1] << 8 | scr[2];
00118 #else
00119         return scr[2] << 16 | scr[1] << 8 | scr[0];
00120 #endif  
00121 }
00122 
00124 static void rgb_2byte(void *dst, int rgb)
00125 {
00126         /* 5-bit, 6-bits, 5-bits */ 
00127         *((__u16 *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | BLUE(rgb, 5);
00128 }
00129 
00131 static int byte2_rgb(void *src)
00132 {
00133         int color = *(__u16 *)(src);
00134         return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
00135 }
00136 
00138 static void rgb_1byte(void *dst, int rgb)
00139 {
00140         *(__u8 *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3);
00141 }
00142 
00144 static int byte1_rgb(void *src)
00145 {
00146         int color = *(__u8 *)src;
00147         return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
00148 }
00149 
00150 static void putpixel(unsigned int x, unsigned int y, int color)
00151 {
00152         (*rgb2scr)(&fbaddress[POINTPOS(x,y)],color);
00153 
00154         if (dbbuffer) {
00155                 int dline = (y + dboffset) % yres;
00156                 (*rgb2scr)(&dbbuffer[POINTPOS(x,dline)],color);
00157         }
00158 }
00159 
00161 static int getpixel(unsigned int x, unsigned int y)
00162 {
00163         if (dbbuffer) {
00164                 int dline = (y + dboffset) % yres;
00165                 return (*scr2rgb)(&dbbuffer[POINTPOS(x,dline)]);
00166         }
00167         return (*scr2rgb)(&fbaddress[POINTPOS(x,y)]);
00168 }
00169 
00170 
00172 static void clear_screen(void)
00173 {
00174         unsigned int y;
00175 
00176         for (y = 0; y < yres; y++) {
00177                 memcpy(&fbaddress[scanline*y], blankline, xres*pixelbytes);
00178                 if (dbbuffer)
00179                         memcpy(&dbbuffer[scanline*y], blankline, xres*pixelbytes);
00180         }
00181 }
00182 
00183 
00185 static void scroll_screen(void)
00186 {
00187         __u8 *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
00188         int firstsz;
00189 
00190         if (dbbuffer) {
00191                 memcpy(&dbbuffer[dboffset*scanline], blankline, FONT_SCANLINES*scanline);
00192                 
00193                 dboffset = (dboffset + FONT_SCANLINES) % yres;
00194                 firstsz = yres-dboffset;
00195 
00196                 memcpy(fbaddress, &dbbuffer[scanline*dboffset], firstsz*scanline);
00197                 memcpy(&fbaddress[firstsz*scanline], dbbuffer, dboffset*scanline);
00198         } else {
00199                 memcpy((void *) fbaddress, (void *) &fbaddress[ROW_BYTES], scanline * yres - ROW_BYTES);
00200                 /* Clear last row */
00201                 memcpy((void *) lastline, (void *) blankline, ROW_BYTES);
00202         }
00203 }
00204 
00205 
00206 static void invert_pixel(unsigned int x, unsigned int y)
00207 {
00208         putpixel(x, y, ~getpixel(x, y));
00209 }
00210 
00211 
00213 static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
00214 {
00215         unsigned int i;
00216 
00217         for (i = 0; i < 8; i++)
00218                 if (glline & (1 << (7 - i))) {
00219                         putpixel(x + i, y, FGCOLOR);
00220                 } else
00221                         putpixel(x + i, y, BGCOLOR);
00222 }
00223 
00224 /***************************************************************/
00225 /* Character-console functions */
00226 
00228 static void draw_glyph(__u8 glyph, unsigned int col, unsigned int row)
00229 {
00230         unsigned int y;
00231 
00232         for (y = 0; y < FONT_SCANLINES; y++)
00233                 draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y], col * COL_WIDTH, row * FONT_SCANLINES + y);
00234 }
00235 
00237 static void invert_char(unsigned int col, unsigned int row)
00238 {
00239         unsigned int x;
00240         unsigned int y;
00241 
00242         for (x = 0; x < COL_WIDTH; x++)
00243                 for (y = 0; y < FONT_SCANLINES; y++)
00244                         invert_pixel(col * COL_WIDTH + x, row * FONT_SCANLINES + y);
00245 }
00246 
00248 static void draw_char(char chr)
00249 {
00250         draw_glyph(chr, position % columns, position / columns);
00251 }
00252 
00253 static void draw_logo(unsigned int startx, unsigned int starty)
00254 {
00255         unsigned int x;
00256         unsigned int y;
00257         unsigned int byte;
00258         unsigned int rowbytes;
00259 
00260         rowbytes = (helenos_width - 1) / 8 + 1;
00261 
00262         for (y = 0; y < helenos_height; y++)
00263                 for (x = 0; x < helenos_width; x++) {
00264                         byte = helenos_bits[rowbytes * y + x / 8];
00265                         byte >>= x % 8;
00266                         if (byte & 1)
00267                                 putpixel(startx + x, starty + y, LOGOCOLOR);
00268                 }
00269 }
00270 
00271 /***************************************************************/
00272 /* Stdout specific functions */
00273 
00274 static void invert_cursor(void)
00275 {
00276         invert_char(position % columns, position / columns);
00277 }
00278 
00283 static void fb_putchar(chardev_t *dev, char ch)
00284 {
00285         spinlock_lock(&fb_lock);
00286         
00287         switch (ch) {
00288                 case '\n':
00289                         invert_cursor();
00290                         position += columns;
00291                         position -= position % columns;
00292                         break;
00293                 case '\r':
00294                         invert_cursor();
00295                         position -= position % columns;
00296                         break;
00297                 case '\b':
00298                         invert_cursor();
00299                         if (position % columns)
00300                                 position--;
00301                         break;
00302                 case '\t':
00303                         invert_cursor();
00304                         do {
00305                                 draw_char(' ');
00306                                 position++;
00307                         } while ((position % 8) && position < columns * rows);
00308                         break;
00309                 default:
00310                         draw_char(ch);
00311                         position++;
00312         }
00313         
00314         if (position >= columns * rows) {
00315                 position -= columns;
00316                 scroll_screen();
00317         }
00318         
00319         invert_cursor();
00320         
00321         spinlock_unlock(&fb_lock);
00322 }
00323 
00324 static chardev_t framebuffer;
00325 static chardev_operations_t fb_ops = {
00326         .write = fb_putchar,
00327 };
00328 
00329 
00339 void fb_init(__address addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan)
00340 {
00341         switch (bpp) {
00342                 case 8:
00343                         rgb2scr = rgb_1byte;
00344                         scr2rgb = byte1_rgb;
00345                         pixelbytes = 1;
00346                         break;
00347                 case 16:
00348                         rgb2scr = rgb_2byte;
00349                         scr2rgb = byte2_rgb;
00350                         pixelbytes = 2;
00351                         break;
00352                 case 24:
00353                         rgb2scr = rgb_3byte;
00354                         scr2rgb = byte3_rgb;
00355                         pixelbytes = 3;
00356                         break;
00357                 case 32:
00358                         rgb2scr = rgb_4byte;
00359                         scr2rgb = byte4_rgb;
00360                         pixelbytes = 4;
00361                         break;
00362                 default:
00363                         panic("Unsupported bpp");
00364         }
00365         
00366         unsigned int fbsize = scan * y;
00367         
00368         /* Map the framebuffer */
00369         fbaddress = (__u8 *) hw_map((__address) addr, fbsize);
00370         
00371         xres = x;
00372         yres = y;
00373         bitspp = bpp;
00374         scanline = scan;
00375         
00376         rows = y / FONT_SCANLINES;
00377         columns = x / COL_WIDTH;
00378 
00379         sysinfo_set_item_val("fb", NULL, true);
00380         sysinfo_set_item_val("fb.kind", NULL, 1);
00381         sysinfo_set_item_val("fb.width", NULL, xres);
00382         sysinfo_set_item_val("fb.height", NULL, yres);
00383         sysinfo_set_item_val("fb.bpp", NULL, bpp);
00384         sysinfo_set_item_val("fb.scanline", NULL, scan);
00385         sysinfo_set_item_val("fb.address.physical", NULL, addr);
00386 
00387         /* Allocate double buffer */
00388         int totsize = scanline * yres;
00389         int pages = SIZE2FRAMES(totsize);
00390         int order;
00391         int rc;
00392         if (pages == 1)
00393                 order = 0;
00394         else
00395                 order = fnzb(pages-1)+1;
00396 
00397         pfn_t frame = frame_alloc_rc(order,FRAME_ATOMIC,&rc);
00398         if (!rc)
00399                 dbbuffer = (void *)PA2KA(PFN2ADDR(frame));
00400         else 
00401                 printf("Failed to allocate scroll buffer.\n");
00402         dboffset = 0;
00403 
00404         /* Initialized blank line */
00405         blankline = (__u8 *) malloc(ROW_BYTES, FRAME_ATOMIC);
00406         ASSERT(blankline);
00407         for (y=0; y < FONT_SCANLINES; y++)
00408                 for (x=0; x < xres; x++)
00409                         (*rgb2scr)(&blankline[POINTPOS(x,y)],BGCOLOR);
00410 
00411         clear_screen();
00412 
00413         /* Update size of screen to match text area */
00414         yres = rows * FONT_SCANLINES;
00415 
00416         draw_logo(xres - helenos_width, 0);
00417         invert_cursor();
00418 
00419         chardev_initialize("fb", &framebuffer, &fb_ops);
00420         stdout = &framebuffer;
00421         
00422 }
00423 

Generated on Sun Jun 18 17:17:04 2006 for HelenOS Kernel (ppc32) by  doxygen 1.4.6