Subversion Repositories HelenOS-historic

Rev

Rev 838 | Rev 886 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2006 Ondrej Palkovsky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include <genarch/fb/font-8x16.h>
  30. #include <genarch/fb/fb.h>
  31. #include <console/chardev.h>
  32. #include <console/console.h>
  33. #include <panic.h>
  34.  
  35. SPINLOCK_INITIALIZE(fb_lock);
  36.  
  37. static __u8 *fbaddress=NULL;
  38. static int xres,yres;
  39. static int position=0;
  40. static int columns=0;
  41. static int rows=0;
  42. static int pixelbytes=0;
  43.  
  44. #define COL_WIDTH   8
  45. #define ROW_HEIGHT  (FONT_SCANLINES)
  46. #define ROW_PIX     (xres*ROW_HEIGHT*pixelbytes)
  47.  
  48. #define BGCOLOR   0x000080
  49. #define FGCOLOR   0xffff00
  50.  
  51. #define RED(x,bits)    ((x >> (16+8-bits)) & ((1<<bits)-1))
  52. #define GREEN(x,bits)  ((x >> (8+8-bits)) & ((1<<bits)-1))
  53. #define BLUE(x,bits)   ((x >> (8-bits)) & ((1<<bits)-1))
  54.  
  55. #define POINTPOS(x,y)   ((y*xres+x)*pixelbytes)
  56.  
  57. /***************************************************************/
  58. /* Pixel specific fuctions */
  59.  
  60. static void (*putpixel)(int x,int y,int color);
  61. static int (*getpixel)(int x,int y);
  62.  
  63. /** Put pixel - 24-bit depth, 1 free byte */
  64. static void putpixel_4byte(int x,int y,int color)
  65. {
  66.     int startbyte = POINTPOS(x,y);
  67.  
  68.     *((__u32 *)(fbaddress+startbyte)) = color;
  69. }
  70.  
  71. /** Return pixel color */
  72. static int getpixel_4byte(int x,int y)
  73. {
  74.     int startbyte = POINTPOS(x,y);
  75.  
  76.     return *((__u32 *)(fbaddress+startbyte)) & 0xffffff;
  77. }
  78.  
  79. /** Draw pixel of given color on screen - 24-bit depth */
  80. static void putpixel_3byte(int x,int y,int color)
  81. {
  82.     int startbyte = POINTPOS(x,y);
  83.  
  84.     fbaddress[startbyte] = RED(color,8);
  85.     fbaddress[startbyte+1] = GREEN(color,8);
  86.     fbaddress[startbyte+2] = BLUE(color,8);
  87. }
  88.  
  89. static int getpixel_3byte(int x,int y)
  90. {
  91.     int startbyte = POINTPOS(x,y);
  92.     int result;
  93.  
  94.     result = fbaddress[startbyte] << 16 \
  95.         | fbaddress[startbyte+1] << 8 \
  96.         | fbaddress[startbyte+2];
  97.     return result;
  98. }
  99.  
  100. /** Put pixel - 16-bit depth (5:6:6) */
  101. static void putpixel_2byte(int x,int y,int color)
  102. {
  103.     int startbyte = POINTPOS(x,y);
  104.     int compcolor;
  105.  
  106.     /* 5-bit, 5-bits, 5-bits */
  107.     compcolor = RED(color,5) << 11 \
  108.         | GREEN(color,6) << 5 \
  109.         | BLUE(color,5);
  110.     *((__u16 *)(fbaddress+startbyte)) = compcolor;
  111. }
  112.  
  113. static int getpixel_2byte(int x,int y)
  114. {
  115.     int startbyte = POINTPOS(x,y);
  116.     int color;
  117.     int red,green,blue;
  118.  
  119.     color = *((__u16 *)(fbaddress+startbyte));
  120.     red = (color >> 11) & 0x1f;
  121.     green = (color >> 5) & 0x3f;
  122.     blue = color & 0x1f;
  123.     return (red << (16+3)) | (green << (8+2)) | (blue << 3);
  124. }
  125.  
  126. /** Put pixel - 8-bit depth (3:3:2) */
  127. static void putpixel_1byte(int x,int y,int color)
  128. {
  129.     int compcolor;
  130.  
  131.     /* 3-bit, 3-bits, 2-bits */
  132.     compcolor = RED(color,3) << 5 \
  133.         | GREEN(color,3) << 2 \
  134.         | BLUE(color,2);
  135.     fbaddress[POINTPOS(x,y)] = compcolor;
  136. }
  137.  
  138.  
  139. static int getpixel_1byte(int x,int y)
  140. {
  141.     int color;
  142.     int red,green,blue;
  143.  
  144.     color = fbaddress[POINTPOS(x,y)];
  145.     red = (color >> 5) & 0x7;
  146.     green = (color >> 5) & 0x7;
  147.     blue = color & 0x3;
  148.     return (red << (16+5)) | (green << (8+5)) | blue << 6;
  149. }
  150.  
  151. static void clear_line(int y);
  152. /** Scroll screen one row up */
  153. static void scroll_screen(void)
  154. {
  155.     int i;
  156.  
  157.     for (i=0;i < (xres*yres*pixelbytes)-ROW_PIX; i++)
  158.         fbaddress[i] = fbaddress[i+ROW_PIX];
  159.  
  160.     /* Clear last row */
  161.     for (i=0; i < ROW_HEIGHT;i++)
  162.         clear_line((rows-1)*ROW_HEIGHT+i);
  163.    
  164. }
  165.  
  166.  
  167. /***************************************************************/
  168. /* Screen specific function */
  169.  
  170. /** Fill line with color BGCOLOR */
  171. static void clear_line(int y)
  172. {
  173.     int x;
  174.     for (x=0; x<xres;x++)
  175.         (*putpixel)(x,y,BGCOLOR);
  176. }
  177.  
  178. /** Fill screen with background color */
  179. static void clear_screen(void)
  180. {
  181.     int y;
  182.  
  183.     for (y=0; y<yres;y++)
  184.         clear_line(y);
  185. }
  186.  
  187. static void invert_pixel(int x, int y)
  188. {
  189.     (*putpixel)(x,y, ~(*getpixel)(x,y));
  190. }
  191.  
  192.  
  193. /** Draw one line of glyph at a given position */
  194. static void draw_glyph_line(int glline, int x, int y)
  195. {
  196.     int i;
  197.  
  198.     for (i=0; i < 8; i++)
  199.         if (glline & (1 << (7-i))) {
  200.             (*putpixel)(x+i,y,FGCOLOR);
  201.         } else
  202.             (*putpixel)(x+i,y,BGCOLOR);
  203. }
  204.  
  205. /***************************************************************/
  206. /* Character-console functions */
  207.  
  208. /** Draw character at given position */
  209. static void draw_glyph(__u8 glyph, int col, int row)
  210. {
  211.     int y;
  212.  
  213.     for (y=0; y < FONT_SCANLINES; y++)
  214.         draw_glyph_line(fb_font[glyph*FONT_SCANLINES+y],
  215.                 col*COL_WIDTH, row*ROW_HEIGHT+y);
  216. }
  217.  
  218. /** Invert character at given position */
  219. static void invert_char(int col, int row)
  220. {
  221.     int x,y;
  222.  
  223.     for (x=0; x < COL_WIDTH; x++)
  224.         for (y=0; y < FONT_SCANLINES; y++)
  225.             invert_pixel(col*COL_WIDTH+x,row*ROW_HEIGHT+y);
  226. }
  227.  
  228. /** Draw character at default position */
  229. static void draw_char(char chr)
  230. {
  231.     draw_glyph(chr, position % columns, position/columns);
  232. }
  233.  
  234. /***************************************************************/
  235. /* Stdout specific functions */
  236.  
  237. static void invert_cursor(void)
  238. {
  239.     invert_char(position % columns, position/columns);
  240. }
  241.  
  242. /** Print character to screen
  243.  *
  244.  *  Emulate basic terminal commands
  245.  */
  246. static void fb_putchar(chardev_t *dev, char ch)
  247. {
  248.     spinlock_lock(&fb->lock);
  249.  
  250.     if (ch == '\n') {
  251.         invert_cursor();
  252.         position += columns;
  253.         position -= position % columns;
  254.     } else if (ch == '\r') {
  255.         invert_cursor();
  256.         position -= position % columns;
  257.     } else if (ch == '\b') {
  258.         invert_cursor();
  259.         if (position % columns)
  260.             position--;
  261.     } else if (ch == '\t') {
  262.         invert_cursor();
  263.         do {
  264.             draw_char(' ');
  265.             position++;
  266.         } while (position % 8);
  267.     } else {
  268.         draw_char(ch);
  269.         position++;
  270.     }
  271.     if (position >= columns*rows) {
  272.         position -= columns;
  273.         scroll_screen();
  274.     }
  275.     invert_cursor();
  276.     spinlock_unlock(&fb->lock);
  277. }
  278.  
  279. static chardev_t framebuffer;
  280. static chardev_operations_t fb_ops = {
  281.     .write = fb_putchar,
  282. };
  283.  
  284.  
  285. /** Initialize framebuffer as a chardev output device
  286.  *
  287.  * @param addr Address of framebuffer
  288.  * @param x X resolution
  289.  * @param y Y resolution
  290.  * @param bytes Bytes per pixel (2,3,4)
  291.  */
  292. void fb_init(__address addr, int x, int y, int bytes)
  293. {
  294.     fbaddress = (unsigned char *)addr;
  295.  
  296.     switch (bytes) {
  297.     case 1:
  298.         putpixel = putpixel_1byte;
  299.         getpixel = getpixel_1byte;
  300.         break;
  301.     case 2:
  302.         putpixel = putpixel_2byte;
  303.         getpixel = getpixel_2byte;
  304.         break;
  305.     case 3:
  306.         putpixel = putpixel_3byte;
  307.         getpixel = getpixel_3byte;
  308.         break;
  309.     case 4:
  310.         putpixel = putpixel_4byte;
  311.         getpixel = getpixel_4byte;
  312.         break;
  313.     default:
  314.         panic("Unsupported color depth");
  315.     }
  316.    
  317.     xres = x;
  318.     yres = y;
  319.     pixelbytes = bytes;
  320.    
  321.     rows = y/ROW_HEIGHT;
  322.     columns = x/COL_WIDTH;
  323.  
  324.     clear_screen();
  325.     invert_cursor();
  326.  
  327.     chardev_initialize("fb", &framebuffer, &fb_ops);
  328.     stdout = &framebuffer;
  329. }
  330.  
  331.