Subversion Repositories HelenOS-historic

Rev

Rev 837 | Rev 839 | 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 <print.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. /** Draw pixel of given color on screen */
  61. static inline void putpixel(int x,int y,int color)
  62. {
  63.     int startbyte = POINTPOS(x,y);
  64.  
  65.     if (pixelbytes == 3) {
  66.         fbaddress[startbyte] = RED(color,8);
  67.         fbaddress[startbyte+1] = GREEN(color,8);
  68.         fbaddress[startbyte+2] = BLUE(color,8);
  69.     } else if (pixelbytes == 4) {
  70.         *((__u32 *)(fbaddress+startbyte)) = color;
  71.     } else {
  72.         int compcolor;
  73.         /* 5-bit, 5-bits, 5-bits */
  74.         compcolor = RED(color,5) << 10 \
  75.             | GREEN(color,5) << 5 \
  76.             | BLUE(color,5);
  77.         *((__u16 *)(fbaddress+startbyte)) = compcolor;
  78.     }
  79. }
  80.  
  81. /** Return pixel color */
  82. static inline int getpixel(int x,int y)
  83. {
  84.     int startbyte = POINTPOS(x,y);
  85.     int color;
  86.     int result;
  87.  
  88.     if (pixelbytes == 3) {
  89.         result = fbaddress[startbyte] << 16 \
  90.             | fbaddress[startbyte+1] << 8 \
  91.             | fbaddress[startbyte+2];
  92.     } else if (pixelbytes == 4) {
  93.         result = *((__u32 *)(fbaddress+startbyte)) & 0xffffff;
  94.     } else {
  95.         int red,green,blue;
  96.         color = *((__u16 *)(fbaddress+startbyte));
  97.         red = (color >> 10) & 0x1f;
  98.         green = (color >> 5) & 0x1f;
  99.         blue = color & 0x1f;
  100.         result = (red << 16) | (green << 8) | blue;
  101.     }
  102.     return result;
  103. }
  104.  
  105. static void clear_line(int y);
  106. /** Scroll screen one row up */
  107. static void scroll_screen(void)
  108. {
  109.     int i;
  110.  
  111.     for (i=0;i < (xres*yres*pixelbytes)-ROW_PIX; i++)
  112.         fbaddress[i] = fbaddress[i+ROW_PIX];
  113.  
  114.     /* Clear last row */
  115.     for (i=0; i < ROW_HEIGHT;i++)
  116.         clear_line((rows-1)*ROW_HEIGHT+i);
  117.    
  118. }
  119.  
  120.  
  121. /***************************************************************/
  122. /* Screen specific function */
  123.  
  124. /** Fill line with color BGCOLOR */
  125. static void clear_line(int y)
  126. {
  127.     int x;
  128.     for (x=0; x<xres;x++)
  129.         putpixel(x,y,BGCOLOR);
  130. }
  131.  
  132. /** Fill screen with background color */
  133. static void clear_screen(void)
  134. {
  135.     int y;
  136.  
  137.     for (y=0; y<yres;y++)
  138.         clear_line(y);
  139. }
  140.  
  141. static void invert_pixel(int x, int y)
  142. {
  143.     putpixel(x,y, ~getpixel(x,y));
  144. }
  145.  
  146.  
  147. /** Draw one line of glyph at a given position */
  148. static void draw_glyph_line(int glline, int x, int y)
  149. {
  150.     int i;
  151.  
  152.     for (i=0; i < 8; i++)
  153.         if (glline & (1 << (7-i))) {
  154.             putpixel(x+i,y,FGCOLOR);
  155.         } else
  156.             putpixel(x+i,y,BGCOLOR);
  157. }
  158.  
  159. /***************************************************************/
  160. /* Character-console functions */
  161.  
  162. /** Draw character at given position */
  163. static void draw_glyph(__u8 glyph, int col, int row)
  164. {
  165.     int y;
  166.  
  167.     for (y=0; y < FONT_SCANLINES; y++)
  168.         draw_glyph_line(fb_font[glyph*FONT_SCANLINES+y],
  169.                 col*COL_WIDTH, row*ROW_HEIGHT+y);
  170. }
  171.  
  172. /** Invert character at given position */
  173. static void invert_char(int col, int row)
  174. {
  175.     int x,y;
  176.  
  177.     for (x=0; x < COL_WIDTH; x++)
  178.         for (y=0; y < FONT_SCANLINES; y++)
  179.             invert_pixel(col*COL_WIDTH+x,row*ROW_HEIGHT+y);
  180. }
  181.  
  182. /** Draw character at default position */
  183. static void draw_char(char chr)
  184. {
  185.     draw_glyph(chr, position % columns, position/columns);
  186. }
  187.  
  188. /***************************************************************/
  189. /* Stdout specific functions */
  190.  
  191. static void invert_cursor(void)
  192. {
  193.     invert_char(position % columns, position/columns);
  194. }
  195.  
  196. /** Print character to screen
  197.  *
  198.  *  Emulate basic terminal commands
  199.  */
  200. static void fb_putchar(chardev_t *dev, char ch)
  201. {
  202.     spinlock_lock(&fb->lock);
  203.  
  204.     if (ch == '\n') {
  205.         invert_cursor();
  206.         position += columns;
  207.         position -= position % columns;
  208.     } else if (ch == '\r') {
  209.         invert_cursor();
  210.         position -= position % columns;
  211.     } else if (ch == '\b') {
  212.         invert_cursor();
  213.         if (position % columns)
  214.             position--;
  215.     } else if (ch == '\t') {
  216.         invert_cursor();
  217.         do {
  218.             draw_char(' ');
  219.             position++;
  220.         } while (position % 8);
  221.     } else {
  222.         draw_char(ch);
  223.         position++;
  224.     }
  225.     if (position >= columns*rows) {
  226.         position -= columns;
  227.         scroll_screen();
  228.     }
  229.     invert_cursor();
  230.     spinlock_unlock(&fb->lock);
  231. }
  232.  
  233. static chardev_t framebuffer;
  234. static chardev_operations_t fb_ops = {
  235.     .write = fb_putchar,
  236. };
  237.  
  238.  
  239. /** Initialize framebuffer as a chardev output device
  240.  *
  241.  * @param addr Address of framebuffer
  242.  * @param x X resolution
  243.  * @param y Y resolution
  244.  * @param bytes Bytes per pixel (2,3,4)
  245.  */
  246. void fb_init(__address addr, int x, int y, int bytes)
  247. {
  248.     fbaddress = (unsigned char *)addr;
  249.    
  250.     xres = x;
  251.     yres = y;
  252.     pixelbytes = bytes;
  253.    
  254.     rows = y/ROW_HEIGHT;
  255.     columns = x/COL_WIDTH;
  256.  
  257.     clear_screen();
  258.     invert_cursor();
  259.  
  260.     chardev_initialize("fb", &framebuffer, &fb_ops);
  261.     stdout = &framebuffer;
  262. }
  263.  
  264.