2 * Copyright (C) 2006 Ondrej Palkovsky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @addtogroup genarch
35 #include <genarch/fb/font-8x16.h>
36 #include <genarch/fb/fb.h>
37 #include <console/chardev.h>
38 #include <console/console.h>
39 #include <sysinfo/sysinfo.h>
48 #include "helenos.xbm"
50 SPINLOCK_INITIALIZE(fb_lock
);
52 static uint8_t *fbaddress
= NULL
;
54 static uint8_t *blankline
= NULL
;
55 static uint8_t *dbbuffer
= NULL
; /* Buffer for fast scrolling console */
58 static unsigned int xres
= 0;
59 static unsigned int yres
= 0;
60 static unsigned int scanline
= 0;
61 static unsigned int bitspp
= 0;
62 static unsigned int pixelbytes
= 0;
63 #ifdef FB_INVERT_COLORS
64 static bool invert_colors
= true;
66 static bool invert_colors
= false;
69 static unsigned int position
= 0;
70 static unsigned int columns
= 0;
71 static unsigned int rows
= 0;
74 #define ROW_BYTES (scanline * FONT_SCANLINES)
76 #define BGCOLOR 0x000080
77 #define FGCOLOR 0xffff00
78 #define LOGOCOLOR 0x2020b0
80 #define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
81 #define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
82 #define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
84 #define POINTPOS(x, y) ((y) * scanline + (x) * pixelbytes)
86 /***************************************************************/
87 /* Pixel specific fuctions */
89 static void (*rgb2scr
)(void *, int);
90 static int (*scr2rgb
)(void *);
92 static inline int COLOR(int color
)
94 return invert_colors
? ~color
: color
;
97 /* Conversion routines between different color representations */
98 static void rgb_4byte(void *dst
, int rgb
)
103 static int byte4_rgb(void *src
)
105 return (*(int *)src
) & 0xffffff;
108 static void rgb_3byte(void *dst
, int rgb
)
111 #if defined(FB_INVERT_ENDIAN)
112 scr
[0] = RED(rgb
, 8);
113 scr
[1] = GREEN(rgb
, 8);
114 scr
[2] = BLUE(rgb
, 8);
116 scr
[2] = RED(rgb
, 8);
117 scr
[1] = GREEN(rgb
, 8);
118 scr
[0] = BLUE(rgb
, 8);
122 static int byte3_rgb(void *src
)
125 #if defined(FB_INVERT_ENDIAN)
126 return scr
[0] << 16 | scr
[1] << 8 | scr
[2];
128 return scr
[2] << 16 | scr
[1] << 8 | scr
[0];
132 /** 16-bit depth (5:6:5) */
133 static void rgb_2byte(void *dst
, int rgb
)
135 /* 5-bit, 6-bits, 5-bits */
136 *((uint16_t *)(dst
)) = RED(rgb
, 5) << 11 | GREEN(rgb
, 6) << 5 | BLUE(rgb
, 5);
139 /** 16-bit depth (5:6:5) */
140 static int byte2_rgb(void *src
)
142 int color
= *(uint16_t *)(src
);
143 return (((color
>> 11) & 0x1f) << (16 + 3)) | (((color
>> 5) & 0x3f) << (8 + 2)) | ((color
& 0x1f) << 3);
146 /** Put pixel - 8-bit depth (color palette/3:2:3)
148 * Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
149 * will most likely use a color palette. The color appearance
150 * will be pretty random and depend on the default installed
151 * palette. This could be fixed by supporting custom palette
152 * and setting it to simulate the 8-bit truecolor.
154 static void rgb_1byte(void *dst
, int rgb
)
156 *(uint8_t *)dst
= RED(rgb
, 3) << 5 | GREEN(rgb
, 2) << 3 | BLUE(rgb
, 3);
159 /** Return pixel color - 8-bit depth (color palette/3:2:3)
161 * See the comment for rgb_1byte().
163 static int byte1_rgb(void *src
)
165 int color
= *(uint8_t *)src
;
166 return (((color
>> 5) & 0x7) << (16 + 5)) | (((color
>> 3) & 0x3) << (8 + 6)) | ((color
& 0x7) << 5);
169 static void putpixel(unsigned int x
, unsigned int y
, int color
)
171 (*rgb2scr
)(&fbaddress
[POINTPOS(x
,y
)], COLOR(color
));
174 int dline
= (y
+ dboffset
) % yres
;
175 (*rgb2scr
)(&dbbuffer
[POINTPOS(x
,dline
)], COLOR(color
));
179 /** Get pixel from viewport */
180 static int getpixel(unsigned int x
, unsigned int y
)
183 int dline
= (y
+ dboffset
) % yres
;
184 return COLOR((*scr2rgb
)(&dbbuffer
[POINTPOS(x
,dline
)]));
186 return COLOR((*scr2rgb
)(&fbaddress
[POINTPOS(x
,y
)]));
190 /** Fill screen with background color */
191 static void clear_screen(void)
195 for (y
= 0; y
< yres
; y
++) {
196 memcpy(&fbaddress
[scanline
*y
], blankline
, xres
*pixelbytes
);
198 memcpy(&dbbuffer
[scanline
*y
], blankline
, xres
*pixelbytes
);
203 /** Scroll screen one row up */
204 static void scroll_screen(void)
206 uint8_t *lastline
= &fbaddress
[(rows
- 1) * ROW_BYTES
];
210 memcpy(&dbbuffer
[dboffset
*scanline
], blankline
, FONT_SCANLINES
*scanline
);
212 dboffset
= (dboffset
+ FONT_SCANLINES
) % yres
;
213 firstsz
= yres
-dboffset
;
215 memcpy(fbaddress
, &dbbuffer
[scanline
*dboffset
], firstsz
*scanline
);
216 memcpy(&fbaddress
[firstsz
*scanline
], dbbuffer
, dboffset
*scanline
);
218 memcpy((void *) fbaddress
, (void *) &fbaddress
[ROW_BYTES
], scanline
* yres
- ROW_BYTES
);
220 memcpy((void *) lastline
, (void *) blankline
, ROW_BYTES
);
225 static void invert_pixel(unsigned int x
, unsigned int y
)
227 putpixel(x
, y
, ~getpixel(x
, y
));
231 /** Draw one line of glyph at a given position */
232 static void draw_glyph_line(unsigned int glline
, unsigned int x
, unsigned int y
)
236 for (i
= 0; i
< 8; i
++)
237 if (glline
& (1 << (7 - i
))) {
238 putpixel(x
+ i
, y
, FGCOLOR
);
240 putpixel(x
+ i
, y
, BGCOLOR
);
243 /***************************************************************/
244 /* Character-console functions */
246 /** Draw character at given position */
247 static void draw_glyph(uint8_t glyph
, unsigned int col
, unsigned int row
)
251 for (y
= 0; y
< FONT_SCANLINES
; y
++)
252 draw_glyph_line(fb_font
[glyph
* FONT_SCANLINES
+ y
], col
* COL_WIDTH
, row
* FONT_SCANLINES
+ y
);
255 /** Invert character at given position */
256 static void invert_char(unsigned int col
, unsigned int row
)
261 for (x
= 0; x
< COL_WIDTH
; x
++)
262 for (y
= 0; y
< FONT_SCANLINES
; y
++)
263 invert_pixel(col
* COL_WIDTH
+ x
, row
* FONT_SCANLINES
+ y
);
266 /** Draw character at default position */
267 static void draw_char(char chr
)
269 draw_glyph(chr
, position
% columns
, position
/ columns
);
272 static void draw_logo(unsigned int startx
, unsigned int starty
)
277 unsigned int rowbytes
;
279 rowbytes
= (helenos_width
- 1) / 8 + 1;
281 for (y
= 0; y
< helenos_height
; y
++)
282 for (x
= 0; x
< helenos_width
; x
++) {
283 byte
= helenos_bits
[rowbytes
* y
+ x
/ 8];
286 putpixel(startx
+ x
, starty
+ y
, COLOR(LOGOCOLOR
));
290 /***************************************************************/
291 /* Stdout specific functions */
293 static void invert_cursor(void)
295 invert_char(position
% columns
, position
/ columns
);
298 /** Print character to screen
300 * Emulate basic terminal commands
302 static void fb_putchar(chardev_t
*dev
, char ch
)
304 spinlock_lock(&fb_lock
);
310 position
-= position
% columns
;
314 position
-= position
% columns
;
318 if (position
% columns
)
326 } while ((position
% 8) && position
< columns
* rows
);
333 if (position
>= columns
* rows
) {
340 spinlock_unlock(&fb_lock
);
343 static chardev_t framebuffer
;
344 static chardev_operations_t fb_ops
= {
349 /** Initialize framebuffer as a chardev output device
351 * @param addr Physical address of the framebuffer
352 * @param x Screen width in pixels
353 * @param y Screen height in pixels
354 * @param bpp Bits per pixel (8, 16, 24, 32)
355 * @param scan Bytes per one scanline
356 * @param align Request alignment for 24bpp mode.
358 void fb_init(uintptr_t addr
, unsigned int x
, unsigned int y
, unsigned int bpp
, unsigned int scan
, bool align
)
385 panic("Unsupported bpp.\n");
388 unsigned int fbsize
= scan
* y
;
390 /* Map the framebuffer */
391 fbaddress
= (uint8_t *) hw_map((uintptr_t) addr
, fbsize
);
398 rows
= y
/ FONT_SCANLINES
;
399 columns
= x
/ COL_WIDTH
;
401 sysinfo_set_item_val("fb", NULL
, true);
402 sysinfo_set_item_val("fb.kind", NULL
, 1);
403 sysinfo_set_item_val("fb.width", NULL
, xres
);
404 sysinfo_set_item_val("fb.height", NULL
, yres
);
405 sysinfo_set_item_val("fb.bpp", NULL
, bpp
);
406 sysinfo_set_item_val("fb.bpp-align", NULL
, align
);
407 sysinfo_set_item_val("fb.scanline", NULL
, scan
);
408 sysinfo_set_item_val("fb.address.physical", NULL
, addr
);
409 sysinfo_set_item_val("fb.invert-colors", NULL
, invert_colors
);
411 /* Allocate double buffer */
412 int totsize
= scanline
* yres
;
413 int pages
= SIZE2FRAMES(totsize
);
418 order
= fnzb(pages
- 1) + 1;
420 dbbuffer
= frame_alloc(order
, FRAME_ATOMIC
| FRAME_KA
);
422 printf("Failed to allocate scroll buffer.\n");
425 /* Initialized blank line */
426 blankline
= (uint8_t *) malloc(ROW_BYTES
, FRAME_ATOMIC
);
428 panic("Failed to allocate blank line for framebuffer.");
429 for (y
=0; y
< FONT_SCANLINES
; y
++) {
430 for (x
=0; x
< xres
; x
++) {
431 (*rgb2scr
)(&blankline
[POINTPOS(x
,y
)], COLOR(BGCOLOR
));
437 /* Update size of screen to match text area */
438 yres
= rows
* FONT_SCANLINES
;
440 draw_logo(xres
- helenos_width
, 0);
443 chardev_initialize("fb", &framebuffer
, &fb_ops
);
444 stdout
= &framebuffer
;