Subversion Repositories HelenOS

Rev

Rev 1317 | Rev 1327 | 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 <sysinfo/sysinfo.h>
  34. #include <mm/slab.h>
  35. #include <panic.h>
  36. #include <memstr.h>
  37. #include <config.h>
  38.  
  39. #include "helenos.xbm"
  40.  
  41. SPINLOCK_INITIALIZE(fb_lock);
  42.  
  43. static __u8 *fbaddress = NULL;
  44.  
  45. static __u8 *blankline = NULL;
  46.  
  47. static unsigned int xres = 0;
  48. static unsigned int yres = 0;
  49. static unsigned int scanline = 0;
  50. static unsigned int pixelbytes = 0;
  51.  
  52. static unsigned int position = 0;
  53. static unsigned int columns = 0;
  54. static unsigned int rows = 0;
  55.  
  56.  
  57. #define COL_WIDTH   8
  58. #define ROW_BYTES   (scanline * FONT_SCANLINES)
  59.  
  60. #define BGCOLOR     0x000080
  61. #define FGCOLOR     0xffff00
  62. #define LOGOCOLOR   0x2020b0
  63.  
  64. #define RED(x, bits)    ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
  65. #define GREEN(x, bits)  ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
  66. #define BLUE(x, bits)   ((x >> (8 - bits)) & ((1 << bits) - 1))
  67.  
  68. #define POINTPOS(x, y)  (y * scanline + x * pixelbytes)
  69.  
  70. /***************************************************************/
  71. /* Pixel specific fuctions */
  72.  
  73. static void (*putpixel)(unsigned int x, unsigned int y, int color);
  74. static int (*getpixel)(unsigned int x, unsigned int y);
  75.  
  76. /** Put pixel - 24-bit depth, 1 free byte */
  77. static void putpixel_4byte(unsigned int x, unsigned int y, int color)
  78. {
  79.     *((__u32 *)(fbaddress + POINTPOS(x, y))) = color;
  80. }
  81.  
  82. /** Return pixel color - 24-bit depth, 1 free byte */
  83. static int getpixel_4byte(unsigned int x, unsigned int y)
  84. {
  85.     return *((__u32 *)(fbaddress + POINTPOS(x, y))) & 0xffffff;
  86. }
  87.  
  88. /** Put pixel - 24-bit depth */
  89. static void putpixel_3byte(unsigned int x, unsigned int y, int color)
  90. {
  91.     unsigned int startbyte = POINTPOS(x, y);
  92.  
  93. #ifdef BIG_ENDIAN
  94.     fbaddress[startbyte] = RED(color, 8);
  95.     fbaddress[startbyte + 1] = GREEN(color, 8);
  96.     fbaddress[startbyte + 2] = BLUE(color, 8);
  97. #else
  98.     fbaddress[startbyte + 2] = RED(color, 8);
  99.     fbaddress[startbyte + 1] = GREEN(color, 8);
  100.     fbaddress[startbyte + 0] = BLUE(color, 8);
  101. #endif 
  102. }
  103.  
  104. /** Return pixel color - 24-bit depth */
  105. static int getpixel_3byte(unsigned int x, unsigned int y)
  106. {
  107.     unsigned int startbyte = POINTPOS(x, y);
  108.  
  109. #ifdef BIG_ENDIAN
  110.     return fbaddress[startbyte] << 16 | fbaddress[startbyte + 1] << 8 | fbaddress[startbyte + 2];
  111. #else
  112.     return fbaddress[startbyte + 2] << 16 | fbaddress[startbyte + 1] << 8 | fbaddress[startbyte + 0];
  113. #endif 
  114. }
  115.  
  116. /** Put pixel - 16-bit depth (5:6:6) */
  117. static void putpixel_2byte(unsigned int x, unsigned int y, int color)
  118. {
  119.     /* 5-bit, 5-bits, 5-bits */
  120.     *((__u16 *)(fbaddress + POINTPOS(x, y))) = RED(color, 5) << 11 | GREEN(color, 6) << 5 | BLUE(color, 5);
  121. }
  122.  
  123. /** Return pixel color - 16-bit depth (5:6:6) */
  124. static int getpixel_2byte(unsigned int x, unsigned int y)
  125. {
  126.     int color = *((__u16 *)(fbaddress + POINTPOS(x, y)));
  127.     return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
  128. }
  129.  
  130. /** Put pixel - 8-bit depth (3:2:3) */
  131. static void putpixel_1byte(unsigned int x, unsigned int y, int color)
  132. {
  133.     fbaddress[POINTPOS(x, y)] = RED(color, 3) << 5 | GREEN(color, 2) << 3 | BLUE(color, 3);
  134. }
  135.  
  136. /** Return pixel color - 8-bit depth (3:2:3) */
  137. static int getpixel_1byte(unsigned int x, unsigned int y)
  138. {
  139.     int color = fbaddress[POINTPOS(x, y)];
  140.     return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
  141. }
  142.  
  143. /** Fill line with color BGCOLOR */
  144. static void clear_line(unsigned int y)
  145. {
  146.     unsigned int x;
  147.    
  148.     for (x = 0; x < xres; x++)
  149.         (*putpixel)(x, y, BGCOLOR);
  150. }
  151.  
  152.  
  153. /** Fill screen with background color */
  154. static void clear_screen(void)
  155. {
  156.     unsigned int y;
  157.  
  158.     for (y = 0; y < yres; y++)
  159.         clear_line(y);
  160. }
  161.  
  162.  
  163. /** Scroll screen one row up */
  164. static void scroll_screen(void)
  165. {
  166.     unsigned int i;
  167.     __u8 *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
  168.  
  169.     memcpy((void *) fbaddress, (void *) &fbaddress[ROW_BYTES], scanline * yres - ROW_BYTES);
  170.  
  171.     /* Clear last row */
  172.     if (blankline) {
  173.         memcpy((void *) lastline, (void *) blankline, ROW_BYTES);
  174.     } else {
  175.         for (i = 0; i < FONT_SCANLINES; i++)
  176.             clear_line((rows - 1) * FONT_SCANLINES + i);
  177.  
  178.         if (config.mm_initialized) {
  179.             /* Save a blank line aside. */
  180.             blankline = (__u8 *) malloc(ROW_BYTES, FRAME_ATOMIC);
  181.             if (blankline)
  182.                 memcpy((void *) blankline, (void *) lastline, ROW_BYTES);
  183.         }
  184.     }
  185. }
  186.  
  187.  
  188. static void invert_pixel(unsigned int x, unsigned int y)
  189. {
  190.     (*putpixel)(x, y, ~(*getpixel)(x, y));
  191. }
  192.  
  193.  
  194. /** Draw one line of glyph at a given position */
  195. static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
  196. {
  197.     unsigned int i;
  198.  
  199.     for (i = 0; i < 8; i++)
  200.         if (glline & (1 << (7 - i))) {
  201.             (*putpixel)(x + i, y, FGCOLOR);
  202.         } else
  203.             (*putpixel)(x + i, y, BGCOLOR);
  204. }
  205.  
  206. /***************************************************************/
  207. /* Character-console functions */
  208.  
  209. /** Draw character at given position */
  210. static void draw_glyph(__u8 glyph, unsigned int col, unsigned int row)
  211. {
  212.     unsigned int y;
  213.  
  214.     for (y = 0; y < FONT_SCANLINES; y++)
  215.         draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y], col * COL_WIDTH, row * FONT_SCANLINES + y);
  216. }
  217.  
  218. /** Invert character at given position */
  219. static void invert_char(unsigned int col, unsigned int row)
  220. {
  221.     unsigned int x;
  222.     unsigned int y;
  223.  
  224.     for (x = 0; x < COL_WIDTH; x++)
  225.         for (y = 0; y < FONT_SCANLINES; y++)
  226.             invert_pixel(col * COL_WIDTH + x, row * FONT_SCANLINES + y);
  227. }
  228.  
  229. /** Draw character at default position */
  230. static void draw_char(char chr)
  231. {
  232.     draw_glyph(chr, position % columns, position / columns);
  233. }
  234.  
  235. static void draw_logo(unsigned int startx, unsigned int starty)
  236. {
  237.     unsigned int x;
  238.     unsigned int y;
  239.     unsigned int byte;
  240.     unsigned int rowbytes;
  241.  
  242.     rowbytes = (helenos_width - 1) / 8 + 1;
  243.  
  244.     for (y = 0; y < helenos_height; y++)
  245.         for (x = 0; x < helenos_width; x++) {
  246.             byte = helenos_bits[rowbytes * y + x / 8];
  247.             byte >>= x % 8;
  248.             if (byte & 1)
  249.                 (*putpixel)(startx + x, starty + y, LOGOCOLOR);
  250.         }
  251. }
  252.  
  253. /***************************************************************/
  254. /* Stdout specific functions */
  255.  
  256. static void invert_cursor(void)
  257. {
  258.     invert_char(position % columns, position / columns);
  259. }
  260.  
  261. /** Print character to screen
  262.  *
  263.  *  Emulate basic terminal commands
  264.  */
  265. static void fb_putchar(chardev_t *dev, char ch)
  266. {
  267.     spinlock_lock(&fb_lock);
  268.    
  269.     switch (ch) {
  270.         case '\n':
  271.             invert_cursor();
  272.             position += columns;
  273.             position -= position % columns;
  274.             break;
  275.         case '\r':
  276.             invert_cursor();
  277.             position -= position % columns;
  278.             break;
  279.         case '\b':
  280.             invert_cursor();
  281.             if (position % columns)
  282.                 position--;
  283.             break;
  284.         case '\t':
  285.             invert_cursor();
  286.             do {
  287.                 draw_char(' ');
  288.                 position++;
  289.             } while ((position % 8) && position < columns * rows);
  290.             break;
  291.         default:
  292.             draw_char(ch);
  293.             position++;
  294.     }
  295.    
  296.     if (position >= columns * rows) {
  297.         position -= columns;
  298.         scroll_screen();
  299.     }
  300.    
  301.     invert_cursor();
  302.    
  303.     spinlock_unlock(&fb_lock);
  304. }
  305.  
  306. static chardev_t framebuffer;
  307. static chardev_operations_t fb_ops = {
  308.     .write = fb_putchar,
  309. };
  310.  
  311.  
  312. /** Initialize framebuffer as a chardev output device
  313.  *
  314.  * @param addr Address of theframebuffer
  315.  * @param x    Screen width in pixels
  316.  * @param y    Screen height in pixels
  317.  * @param bpp  Bits per pixel (8, 16, 24, 32)
  318.  * @param scan Bytes per one scanline
  319.  *
  320.  */
  321. void fb_init(__address addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan)
  322. {
  323.     switch (bpp) {
  324.         case 8:
  325.             putpixel = putpixel_1byte;
  326.             getpixel = getpixel_1byte;
  327.             pixelbytes = 1;
  328.             break;
  329.         case 16:
  330.             putpixel = putpixel_2byte;
  331.             getpixel = getpixel_2byte;
  332.             pixelbytes = 2;
  333.             break;
  334.         case 24:
  335.             putpixel = putpixel_3byte;
  336.             getpixel = getpixel_3byte;
  337.             pixelbytes = 3;
  338.             break;
  339.         case 32:
  340.             putpixel = putpixel_4byte;
  341.             getpixel = getpixel_4byte;
  342.             pixelbytes = 4;
  343.             break;
  344.         default:
  345.             panic("Unsupported bpp");
  346.     }
  347.        
  348.     fbaddress = (unsigned char *) addr;
  349.     xres = x;
  350.     yres = y;
  351.     scanline = scan;
  352.    
  353.     rows = y / FONT_SCANLINES;
  354.     columns = x / COL_WIDTH;
  355.  
  356.     clear_screen();
  357.     draw_logo(xres - helenos_width, 0);
  358.     invert_cursor();
  359.  
  360.     chardev_initialize("fb", &framebuffer, &fb_ops);
  361.     stdout = &framebuffer;
  362.    
  363.     sysinfo_set_item_val("Framebuffer",NULL,true);
  364.     sysinfo_set_item_val("Framebuffer.width",NULL,x);
  365.     sysinfo_set_item_val("Framebuffer.height",NULL,y);
  366.     sysinfo_set_item_val("Framebuffer.scanline",NULL,scan);
  367.     sysinfo_set_item_val("Framebuffer.bpp",NULL,bpp);
  368.     sysinfo_set_item_val("Framebuffer.address.virtual",NULL,addr);
  369.    
  370.  
  371.  
  372. }
  373.