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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fc46884 was 06e1e95, checked in by Jakub Jermar <jakub@…>, 19 years ago

C99 compliant header guards (hopefully) everywhere in the kernel.
Formatting and indentation changes.
Small improvements in sparc64.

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