source: mainline/kernel/genarch/src/fb/fb.c@ 11675207

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 11675207 was 11675207, checked in by jermar <jermar@…>, 17 years ago

Move everything to kernel/.

  • Property mode set to 100644
File size: 10.3 KB
Line 
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 /** @addtogroup genarch
30 * @{
31 */
32/** @file
33 */
34
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>
40#include <mm/slab.h>
41#include <align.h>
42#include <panic.h>
43#include <memstr.h>
44#include <config.h>
45#include <bitops.h>
46#include <print.h>
47
48#include "helenos.xbm"
49
50SPINLOCK_INITIALIZE(fb_lock);
51
52static uint8_t *fbaddress = NULL;
53
54static uint8_t *blankline = NULL;
55static uint8_t *dbbuffer = NULL; /* Buffer for fast scrolling console */
56static int dboffset;
57
58static unsigned int xres = 0;
59static unsigned int yres = 0;
60static unsigned int scanline = 0;
61static unsigned int bitspp = 0;
62static unsigned int pixelbytes = 0;
63
64static unsigned int position = 0;
65static unsigned int columns = 0;
66static unsigned int rows = 0;
67
68
69#define COL_WIDTH 8
70#define ROW_BYTES (scanline * FONT_SCANLINES)
71
72#define BGCOLOR 0x000080
73#define FGCOLOR 0xffff00
74#define LOGOCOLOR 0x2020b0
75
76#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
77#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
78#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
79
80#define POINTPOS(x, y) ((y) * scanline + (x) * pixelbytes)
81
82/***************************************************************/
83/* Pixel specific fuctions */
84
85static void (*rgb2scr)(void *, int);
86static int (*scr2rgb)(void *);
87
88/* Conversion routines between different color representations */
89static void rgb_4byte(void *dst, int rgb)
90{
91 *(int *)dst = rgb;
92}
93
94static int byte4_rgb(void *src)
95{
96 return (*(int *)src) & 0xffffff;
97}
98
99static void rgb_3byte(void *dst, int rgb)
100{
101 uint8_t *scr = dst;
102#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
103 scr[0] = RED(rgb, 8);
104 scr[1] = GREEN(rgb, 8);
105 scr[2] = BLUE(rgb, 8);
106#else
107 scr[2] = RED(rgb, 8);
108 scr[1] = GREEN(rgb, 8);
109 scr[0] = BLUE(rgb, 8);
110#endif
111}
112
113static int byte3_rgb(void *src)
114{
115 uint8_t *scr = src;
116#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
117 return scr[0] << 16 | scr[1] << 8 | scr[2];
118#else
119 return scr[2] << 16 | scr[1] << 8 | scr[0];
120#endif
121}
122
123/** 16-bit depth (5:6:5) */
124static void rgb_2byte(void *dst, int rgb)
125{
126 /* 5-bit, 6-bits, 5-bits */
127 *((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | BLUE(rgb, 5);
128}
129
130/** 16-bit depth (5:6:5) */
131static int byte2_rgb(void *src)
132{
133 int color = *(uint16_t *)(src);
134 return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
135}
136
137/** Put pixel - 8-bit depth (3:2:3) */
138static void rgb_1byte(void *dst, int rgb)
139{
140 *(uint8_t *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3);
141}
142
143/** Return pixel color - 8-bit depth (3:2:3) */
144static int byte1_rgb(void *src)
145{
146 int color = *(uint8_t *)src;
147 return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
148}
149
150static void putpixel(unsigned int x, unsigned int y, int color)
151{
152 (*rgb2scr)(&fbaddress[POINTPOS(x,y)],color);
153
154 if (dbbuffer) {
155 int dline = (y + dboffset) % yres;
156 (*rgb2scr)(&dbbuffer[POINTPOS(x,dline)],color);
157 }
158}
159
160/** Get pixel from viewport */
161static int getpixel(unsigned int x, unsigned int y)
162{
163 if (dbbuffer) {
164 int dline = (y + dboffset) % yres;
165 return (*scr2rgb)(&dbbuffer[POINTPOS(x,dline)]);
166 }
167 return (*scr2rgb)(&fbaddress[POINTPOS(x,y)]);
168}
169
170
171/** Fill screen with background color */
172static void clear_screen(void)
173{
174 unsigned int y;
175
176 for (y = 0; y < yres; y++) {
177 memcpy(&fbaddress[scanline*y], blankline, xres*pixelbytes);
178 if (dbbuffer)
179 memcpy(&dbbuffer[scanline*y], blankline, xres*pixelbytes);
180 }
181}
182
183
184/** Scroll screen one row up */
185static void scroll_screen(void)
186{
187 uint8_t *lastline = &fbaddress[(rows - 1) * ROW_BYTES];
188 int firstsz;
189
190 if (dbbuffer) {
191 memcpy(&dbbuffer[dboffset*scanline], blankline, FONT_SCANLINES*scanline);
192
193 dboffset = (dboffset + FONT_SCANLINES) % yres;
194 firstsz = yres-dboffset;
195
196 memcpy(fbaddress, &dbbuffer[scanline*dboffset], firstsz*scanline);
197 memcpy(&fbaddress[firstsz*scanline], dbbuffer, dboffset*scanline);
198 } else {
199 memcpy((void *) fbaddress, (void *) &fbaddress[ROW_BYTES], scanline * yres - ROW_BYTES);
200 /* Clear last row */
201 memcpy((void *) lastline, (void *) blankline, ROW_BYTES);
202 }
203}
204
205
206static void invert_pixel(unsigned int x, unsigned int y)
207{
208 putpixel(x, y, ~getpixel(x, y));
209}
210
211
212/** Draw one line of glyph at a given position */
213static void draw_glyph_line(unsigned int glline, unsigned int x, unsigned int y)
214{
215 unsigned int i;
216
217 for (i = 0; i < 8; i++)
218 if (glline & (1 << (7 - i))) {
219 putpixel(x + i, y, FGCOLOR);
220 } else
221 putpixel(x + i, y, BGCOLOR);
222}
223
224/***************************************************************/
225/* Character-console functions */
226
227/** Draw character at given position */
228static void draw_glyph(uint8_t glyph, unsigned int col, unsigned int row)
229{
230 unsigned int y;
231
232 for (y = 0; y < FONT_SCANLINES; y++)
233 draw_glyph_line(fb_font[glyph * FONT_SCANLINES + y], col * COL_WIDTH, row * FONT_SCANLINES + y);
234}
235
236/** Invert character at given position */
237static void invert_char(unsigned int col, unsigned int row)
238{
239 unsigned int x;
240 unsigned int y;
241
242 for (x = 0; x < COL_WIDTH; x++)
243 for (y = 0; y < FONT_SCANLINES; y++)
244 invert_pixel(col * COL_WIDTH + x, row * FONT_SCANLINES + y);
245}
246
247/** Draw character at default position */
248static void draw_char(char chr)
249{
250 draw_glyph(chr, position % columns, position / columns);
251}
252
253static void draw_logo(unsigned int startx, unsigned int starty)
254{
255 unsigned int x;
256 unsigned int y;
257 unsigned int byte;
258 unsigned int rowbytes;
259
260 rowbytes = (helenos_width - 1) / 8 + 1;
261
262 for (y = 0; y < helenos_height; y++)
263 for (x = 0; x < helenos_width; x++) {
264 byte = helenos_bits[rowbytes * y + x / 8];
265 byte >>= x % 8;
266 if (byte & 1)
267 putpixel(startx + x, starty + y, LOGOCOLOR);
268 }
269}
270
271/***************************************************************/
272/* Stdout specific functions */
273
274static void invert_cursor(void)
275{
276 invert_char(position % columns, position / columns);
277}
278
279/** Print character to screen
280 *
281 * Emulate basic terminal commands
282 */
283static void fb_putchar(chardev_t *dev, char ch)
284{
285 spinlock_lock(&fb_lock);
286
287 switch (ch) {
288 case '\n':
289 invert_cursor();
290 position += columns;
291 position -= position % columns;
292 break;
293 case '\r':
294 invert_cursor();
295 position -= position % columns;
296 break;
297 case '\b':
298 invert_cursor();
299 if (position % columns)
300 position--;
301 break;
302 case '\t':
303 invert_cursor();
304 do {
305 draw_char(' ');
306 position++;
307 } while ((position % 8) && position < columns * rows);
308 break;
309 default:
310 draw_char(ch);
311 position++;
312 }
313
314 if (position >= columns * rows) {
315 position -= columns;
316 scroll_screen();
317 }
318
319 invert_cursor();
320
321 spinlock_unlock(&fb_lock);
322}
323
324static chardev_t framebuffer;
325static chardev_operations_t fb_ops = {
326 .write = fb_putchar,
327};
328
329
330/** Initialize framebuffer as a chardev output device
331 *
332 * @param addr Physical address of the framebuffer
333 * @param x Screen width in pixels
334 * @param y Screen height in pixels
335 * @param bpp Bits per pixel (8, 16, 24, 32)
336 * @param scan Bytes per one scanline
337 *
338 */
339void fb_init(uintptr_t addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan)
340{
341 switch (bpp) {
342 case 8:
343 rgb2scr = rgb_1byte;
344 scr2rgb = byte1_rgb;
345 pixelbytes = 1;
346 break;
347 case 16:
348 rgb2scr = rgb_2byte;
349 scr2rgb = byte2_rgb;
350 pixelbytes = 2;
351 break;
352 case 24:
353 rgb2scr = rgb_3byte;
354 scr2rgb = byte3_rgb;
355 pixelbytes = 3;
356 break;
357 case 32:
358 rgb2scr = rgb_4byte;
359 scr2rgb = byte4_rgb;
360 pixelbytes = 4;
361 break;
362 default:
363 panic("Unsupported bpp");
364 }
365
366 unsigned int fbsize = scan * y;
367
368 /* Map the framebuffer */
369 fbaddress = (uint8_t *) hw_map((uintptr_t) addr, fbsize);
370
371 xres = x;
372 yres = y;
373 bitspp = bpp;
374 scanline = scan;
375
376 rows = y / FONT_SCANLINES;
377 columns = x / COL_WIDTH;
378
379 sysinfo_set_item_val("fb", NULL, true);
380 sysinfo_set_item_val("fb.kind", NULL, 1);
381 sysinfo_set_item_val("fb.width", NULL, xres);
382 sysinfo_set_item_val("fb.height", NULL, yres);
383 sysinfo_set_item_val("fb.bpp", NULL, bpp);
384 sysinfo_set_item_val("fb.scanline", NULL, scan);
385 sysinfo_set_item_val("fb.address.physical", NULL, addr);
386
387 /* Allocate double buffer */
388 int totsize = scanline * yres;
389 int pages = SIZE2FRAMES(totsize);
390 int order;
391 if (pages == 1)
392 order = 0;
393 else
394 order = fnzb(pages-1)+1;
395
396 dbbuffer = frame_alloc(order,FRAME_ATOMIC | FRAME_KA);
397 if (!dbbuffer)
398 printf("Failed to allocate scroll buffer.\n");
399 dboffset = 0;
400
401 /* Initialized blank line */
402 blankline = (uint8_t *) malloc(ROW_BYTES, FRAME_ATOMIC);
403 if (!blankline)
404 panic("Failed to allocate blank line for framebuffer.");
405 for (y=0; y < FONT_SCANLINES; y++)
406 for (x=0; x < xres; x++)
407 (*rgb2scr)(&blankline[POINTPOS(x,y)],BGCOLOR);
408
409 clear_screen();
410
411 /* Update size of screen to match text area */
412 yres = rows * FONT_SCANLINES;
413
414 draw_logo(xres - helenos_width, 0);
415 invert_cursor();
416
417 chardev_initialize("fb", &framebuffer, &fb_ops);
418 stdout = &framebuffer;
419
420}
421
422 /** @}
423 */
424
Note: See TracBrowser for help on using the repository browser.