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

Last change on this file was eb2187c4, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 2 months ago

Revert part of the prior commit

This doesn't seem to work right yet.

  • Property mode set to 100644
File size: 18.2 KB
RevLine 
[bbf5657]1/*
[76fca31]2 * Copyright (c) 2008 Martin Decky
[df4ed85]3 * Copyright (c) 2006 Ondrej Palkovsky
[bbf5657]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
[6404aca]30/** @addtogroup kernel_genarch
[b45c443]31 * @{
32 */
33/** @file
34 */
35
[63e27ef]36#include <assert.h>
37#include <debug.h>
[fe050b7]38#include <genarch/fb/font-8x16.h>
39#include <genarch/fb/fb.h>
[bbf5657]40#include <console/chardev.h>
41#include <console/console.h>
[2666daa]42#include <sysinfo/sysinfo.h>
[d4673296]43#include <mm/km.h>
[aafed15]44#include <stdlib.h>
[76fca31]45#include <align.h>
[fcbca14f]46#include <panic.h>
[b169619]47#include <memw.h>
[74d1d66]48#include <config.h>
[6eb96fce]49#include <bitops.h>
[19f857a]50#include <str.h>
[f8ddd17]51#include <ddi/ddi.h>
[d99c1d2]52#include <typedefs.h>
[30885b9]53#include <byteorder.h>
[bbf5657]54
[d2b66d4]55#define BG_COLOR 0x001620
56#define FG_COLOR 0xf3cf65
[a71c158]57#define INV_COLOR 0xaaaaaa
[6e71a9d8]58
[7ddc2c7]59#define FB_PAGES 8
60
[a71c158]61#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
62#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
63#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
[76fca31]64
[a71c158]65#define COL2X(col) ((col) * FONT_WIDTH)
66#define ROW2Y(row) ((row) * FONT_SCANLINES)
[bbf5657]67
[a71c158]68#define X2COL(x) ((x) / FONT_WIDTH)
69#define Y2ROW(y) ((y) / FONT_SCANLINES)
[bbf5657]70
[a71c158]71#define FB_POS(instance, x, y) \
72 ((y) * (instance)->scanline + (x) * (instance)->pixelbytes)
[a2c4445]73
[a71c158]74#define BB_POS(instance, col, row) \
[7ddc2c7]75 ((((instance)->start_row + (row)) % (instance)->rows) * \
76 (instance)->cols + (col))
[a2c4445]77
[ca645a2]78#define BB_NEXT_COL(pos) (++(pos))
79
[a71c158]80#define GLYPH_POS(instance, glyph, y) \
81 ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
[95c7526]82
[888c06e]83#define TAB_WIDTH 8
84
[3bacee1]85typedef void (*rgb_conv_t)(void *, uint32_t);
[bbf5657]86
[a71c158]87typedef struct {
[c263c77]88 SPINLOCK_DECLARE(lock);
[a35b458]89
[b366a6f4]90 parea_t parea;
[a35b458]91
[a71c158]92 uint8_t *addr;
93 uint16_t *backbuf;
94 uint8_t *glyphs;
95 uint8_t *bgscan;
[a35b458]96
[a71c158]97 rgb_conv_t rgb_conv;
[a35b458]98
[a71c158]99 unsigned int xres;
100 unsigned int yres;
[a35b458]101
[7ddc2c7]102 /** Number of rows that fit on framebuffer */
[888c06e]103 unsigned int screen_rows;
[a35b458]104
[a71c158]105 unsigned int scanline;
106 unsigned int glyphscanline;
[a35b458]107
[a71c158]108 unsigned int pixelbytes;
109 unsigned int glyphbytes;
110 unsigned int bgscanbytes;
[a35b458]111
[7ddc2c7]112 /** Number of columns in the backbuffer */
[a71c158]113 unsigned int cols;
[7ddc2c7]114 /** Number of rows in the backbuffer */
[a71c158]115 unsigned int rows;
[a35b458]116
[7ddc2c7]117 /** Starting row in the cyclic backbuffer */
118 unsigned int start_row;
[a35b458]119
[7ddc2c7]120 /** Top-most visible row (relative to start_row) */
121 unsigned int offset_row;
[a35b458]122
[7ddc2c7]123 /** Current backbuffer position */
[a71c158]124 unsigned int position;
[39e1b9a]125
126 /** Partial character between writes */
127 mbstate_t mbstate;
[888c06e]128
129 unsigned int row;
130 unsigned int column;
[a71c158]131} fb_instance_t;
[fcbca14f]132
[39e1b9a]133static void fb_write(outdev_t *, const char *, size_t);
[7ddc2c7]134static void fb_redraw(outdev_t *);
135static void fb_scroll_up(outdev_t *);
136static void fb_scroll_down(outdev_t *);
[253f35a1]137
[a71c158]138static outdev_operations_t fbdev_ops = {
[39e1b9a]139 .write = fb_write,
[7ddc2c7]140 .redraw = fb_redraw,
141 .scroll_up = fb_scroll_up,
142 .scroll_down = fb_scroll_down
[a71c158]143};
[95c7526]144
[30885b9]145/*
146 * RGB conversion functions.
[76fca31]147 *
[30885b9]148 * These functions write an RGB value to some memory in some predefined format.
149 * The naming convention corresponds to the format created by these functions.
150 * The functions use the so called network order (i.e. big endian) with respect
151 * to their names.
[76fca31]152 */
[30885b9]153
[76fca31]154static void rgb_0888(void *dst, uint32_t rgb)
[ccb0cbc]155{
[30885b9]156 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
157 (RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
[ccb0cbc]158}
159
[76fca31]160static void bgr_0888(void *dst, uint32_t rgb)
[ccb0cbc]161{
[30885b9]162 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
163 (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
[ccb0cbc]164}
165
[6ac14a70]166static void rgb_8880(void *dst, uint32_t rgb)
167{
[30885b9]168 *((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
169 (GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
[6ac14a70]170}
171
[30885b9]172static void bgr_8880(void *dst, uint32_t rgb)
173{
174 *((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
175 (GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
176}
[76fca31]177
178static void rgb_888(void *dst, uint32_t rgb)
[fcbca14f]179{
[30885b9]180 ((uint8_t *) dst)[0] = RED(rgb, 8);
[6e71a9d8]181 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
[30885b9]182 ((uint8_t *) dst)[2] = BLUE(rgb, 8);
[95b9963]183}
184
185static void bgr_888(void *dst, uint32_t rgb)
186{
[30885b9]187 ((uint8_t *) dst)[0] = BLUE(rgb, 8);
[95b9963]188 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
[30885b9]189 ((uint8_t *) dst)[2] = RED(rgb, 8);
[fcbca14f]190}
191
[19490ce]192static void rgb_555_be(void *dst, uint32_t rgb)
[2bc137c2]193{
[19490ce]194 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
195 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
[2bc137c2]196}
197
[19490ce]198static void rgb_555_le(void *dst, uint32_t rgb)
[fcbca14f]199{
[19490ce]200 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
201 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
202}
203
204static void rgb_565_be(void *dst, uint32_t rgb)
205{
206 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
207 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
208}
209
210static void rgb_565_le(void *dst, uint32_t rgb)
211{
212 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
213 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
[fcbca14f]214}
215
[30885b9]216/** BGR 3:2:3
[b4fa652]217 *
218 * Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
219 * will most likely use a color palette. The color appearance
220 * will be pretty random and depend on the default installed
221 * palette. This could be fixed by supporting custom palette
222 * and setting it to simulate the 8-bit truecolor.
[925fdd7]223 *
[a71c158]224 * Currently we set the palette on the ia32, amd64, ppc32 and sparc64 port.
[925fdd7]225 *
226 * Note that the byte is being inverted by this function. The reason is
227 * that we would like to use a color palette where the white color code
[882d7a8]228 * is 0 and the black color code is 255, as some machines (Sun Blade 1500)
[925fdd7]229 * use these codes for black and white and prevent to set codes
230 * 0 and 255 to other colors.
[882d7a8]231 *
[b4fa652]232 */
[30885b9]233static void bgr_323(void *dst, uint32_t rgb)
[fcbca14f]234{
[3bacee1]235 *((uint8_t *) dst) =
236 ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
[fcbca14f]237}
238
[76fca31]239/** Draw character at given position
[b4fa652]240 *
241 */
[a71c158]242static void glyph_draw(fb_instance_t *instance, uint16_t glyph,
[b366a6f4]243 unsigned int col, unsigned int row, bool overlay)
[bbf5657]244{
[c8bf88d]245 if (!overlay)
[a71c158]246 instance->backbuf[BB_POS(instance, col, row)] = glyph;
[a35b458]247
[7ddc2c7]248 /* Do not output if the framebuffer is used by user space */
249 if ((instance->parea.mapped) && (!console_override))
250 return;
[a35b458]251
[7ddc2c7]252 /* Check whether the glyph should be visible */
253 if (row < instance->offset_row)
254 return;
[a35b458]255
[7ddc2c7]256 unsigned int rel_row = row - instance->offset_row;
[888c06e]257 if (rel_row >= instance->screen_rows)
[7ddc2c7]258 return;
[a35b458]259
[7ddc2c7]260 unsigned int x = COL2X(col);
261 unsigned int y = ROW2Y(rel_row);
[a35b458]262
[7ddc2c7]263 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++)
264 memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
265 &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
266 instance->glyphscanline);
[bbf5657]267}
268
[eb2187c4]269/** Scroll screen down by one row
270 *
271 */
272static void screen_scroll(fb_instance_t *instance)
273{
274 if ((!instance->parea.mapped) || (console_override)) {
275 for (unsigned int rel_row = 0; rel_row < instance->screen_rows; rel_row++) {
276 unsigned int y = ROW2Y(rel_row);
277 unsigned int row = rel_row + instance->offset_row;
278
279 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
280 unsigned int x;
281 unsigned int col;
282 size_t bb_pos = BB_POS(instance, 0, row);
283 size_t bb_pos1 = BB_POS(instance, 0, row + 1);
284
285 for (col = 0, x = 0; col < instance->cols;
286 col++, x += FONT_WIDTH) {
287 uint16_t glyph;
288
289 if (row < instance->rows - 1) {
290 if (instance->backbuf[bb_pos] ==
291 instance->backbuf[bb_pos1])
292 goto skip;
293
294 glyph = instance->backbuf[bb_pos1];
295 } else
296 glyph = 0;
297
298 memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
299 &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
300 instance->glyphscanline);
301 skip:
302 BB_NEXT_COL(bb_pos);
303 BB_NEXT_COL(bb_pos1);
304 }
305 }
306 }
307 }
308
309 /*
310 * Implement backbuffer scrolling by wrapping around
311 * the cyclic buffer.
312 */
313
314 instance->start_row++;
315 if (instance->start_row == instance->rows)
316 instance->start_row = 0;
317
318 memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
319 instance->cols, 0);
320}
321
[b366a6f4]322static void cursor_put(fb_instance_t *instance)
[bbf5657]323{
[888c06e]324 unsigned int col = instance->column;
325 unsigned int row = instance->row;
[a35b458]326
[b366a6f4]327 glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
[bbf5657]328}
329
[b366a6f4]330static void cursor_remove(fb_instance_t *instance)
[bbf5657]331{
[888c06e]332 unsigned int col = instance->column;
333 unsigned int row = instance->row;
[a35b458]334
[a71c158]335 glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
[b366a6f4]336 col, row, true);
[bbf5657]337}
338
[76fca31]339/** Render glyphs
340 *
341 * Convert glyphs from device independent font
342 * description to current visual representation.
343 *
344 */
[a71c158]345static void glyphs_render(fb_instance_t *instance)
[76fca31]346{
[6e71a9d8]347 /* Prerender glyphs */
[dcdc31d]348 uint16_t glyph;
[a35b458]349
[76fca31]350 for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
[98895c5c]351 uint32_t fg_color;
[a35b458]352
[98895c5c]353 if (glyph == FONT_GLYPHS - 1)
354 fg_color = INV_COLOR;
355 else
356 fg_color = FG_COLOR;
[a35b458]357
[76fca31]358 unsigned int y;
[a35b458]359
[76fca31]360 for (y = 0; y < FONT_SCANLINES; y++) {
361 unsigned int x;
[a35b458]362
[edf5774]363 for (x = 0; x < FONT_WIDTH; x++) {
[a71c158]364 void *dst =
365 &instance->glyphs[GLYPH_POS(instance, glyph, y) +
366 x * instance->pixelbytes];
[dcdc31d]367 uint32_t rgb = (fb_font[glyph][y] &
[98895c5c]368 (1 << (7 - x))) ? fg_color : BG_COLOR;
[a71c158]369 instance->rgb_conv(dst, rgb);
[edf5774]370 }
[76fca31]371 }
372 }
[a35b458]373
[6e71a9d8]374 /* Prerender background scanline */
375 unsigned int x;
[a35b458]376
[a71c158]377 for (x = 0; x < instance->xres; x++)
378 instance->rgb_conv(&instance->bgscan[x * instance->pixelbytes], BG_COLOR);
[76fca31]379}
380
[7ddc2c7]381static void fb_redraw_internal(fb_instance_t *instance)
382{
[888c06e]383 for (unsigned int rel_row = 0; rel_row < instance->screen_rows; rel_row++) {
[7ddc2c7]384 unsigned int y = ROW2Y(rel_row);
385 unsigned int row = rel_row + instance->offset_row;
[a35b458]386
[7ddc2c7]387 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) {
388 unsigned int x;
389 unsigned int col;
[ca645a2]390 size_t bb_pos = BB_POS(instance, 0, row);
[a35b458]391
[7ddc2c7]392 for (col = 0, x = 0; col < instance->cols;
393 col++, x += FONT_WIDTH) {
394 uint16_t glyph =
[ca645a2]395 instance->backbuf[bb_pos];
[7ddc2c7]396 void *dst = &instance->addr[FB_POS(instance, x, y + yd)];
397 void *src = &instance->glyphs[GLYPH_POS(instance, glyph, yd)];
398 memcpy(dst, src, instance->glyphscanline);
[ca645a2]399 BB_NEXT_COL(bb_pos);
[7ddc2c7]400 }
401 }
402 }
[a35b458]403
[7ddc2c7]404 if (COL2X(instance->cols) < instance->xres) {
405 unsigned int y;
406 unsigned int size =
407 (instance->xres - COL2X(instance->cols)) * instance->pixelbytes;
[a35b458]408
[7ddc2c7]409 for (y = 0; y < instance->yres; y++)
410 memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)],
411 instance->bgscan, size);
412 }
[a35b458]413
[888c06e]414 if (ROW2Y(instance->screen_rows) < instance->yres) {
[7ddc2c7]415 unsigned int y;
[a35b458]416
[888c06e]417 for (y = ROW2Y(instance->screen_rows); y < instance->yres; y++)
[7ddc2c7]418 memcpy(&instance->addr[FB_POS(instance, 0, y)],
419 instance->bgscan, instance->bgscanbytes);
420 }
421}
422
[888c06e]423static void _advance_row(fb_instance_t *instance)
424{
425 instance->column = 0;
426 instance->row++;
427}
428
429static void _advance_column(fb_instance_t *instance)
430{
431 instance->column++;
432 if (instance->column == instance->cols)
433 _advance_row(instance);
434}
435
[a71c158]436/** Print character to screen
437 *
438 * Emulate basic terminal commands.
[76fca31]439 *
440 */
[39e1b9a]441static void _putuchar(fb_instance_t *instance, char32_t ch)
[76fca31]442{
[a71c158]443 switch (ch) {
444 case '\n':
[888c06e]445 _advance_row(instance);
[a71c158]446 break;
447 case '\r':
[888c06e]448 instance->column = 0;
[a71c158]449 break;
450 case '\b':
[888c06e]451 if (instance->column > 0)
452 instance->column--;
[a71c158]453 break;
454 case '\t':
455 do {
456 glyph_draw(instance, fb_font_glyph(' '),
[888c06e]457 instance->column,
458 instance->row, false);
459 _advance_column(instance);
460 } while (instance->column % TAB_WIDTH != 0);
[a71c158]461 break;
462 default:
463 glyph_draw(instance, fb_font_glyph(ch),
[888c06e]464 instance->column,
465 instance->row, false);
466 _advance_column(instance);
[a71c158]467 }
[a35b458]468
[888c06e]469 while (instance->row >= instance->rows) {
470 instance->row--;
[b366a6f4]471 screen_scroll(instance);
[a71c158]472 }
[39e1b9a]473}
[a35b458]474
[39e1b9a]475static void fb_write(outdev_t *dev, const char *s, size_t n)
476{
477 fb_instance_t *instance = (fb_instance_t *) dev->data;
478
479 spinlock_lock(&instance->lock);
480 cursor_remove(instance);
[a35b458]481
[39e1b9a]482 size_t offset = 0;
483 char32_t ch;
484
485 while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))
486 _putuchar(instance, ch);
487
488 cursor_put(instance);
[c263c77]489 spinlock_unlock(&instance->lock);
[a71c158]490}
491
[7ddc2c7]492/** Scroll the framebuffer up
493 *
494 */
495static void fb_scroll_up(outdev_t *dev)
[a71c158]496{
[7ddc2c7]497 fb_instance_t *instance = (fb_instance_t *) dev->data;
498 spinlock_lock(&instance->lock);
[a35b458]499
[888c06e]500 if (instance->offset_row >= instance->screen_rows / 2)
501 instance->offset_row -= instance->screen_rows / 2;
[7ddc2c7]502 else
503 instance->offset_row = 0;
[a35b458]504
[7ddc2c7]505 fb_redraw_internal(instance);
506 cursor_put(instance);
[a35b458]507
[7ddc2c7]508 spinlock_unlock(&instance->lock);
509}
510
511/** Scroll the framebuffer down
512 *
513 */
514static void fb_scroll_down(outdev_t *dev)
515{
516 fb_instance_t *instance = (fb_instance_t *) dev->data;
517 spinlock_lock(&instance->lock);
[a35b458]518
[888c06e]519 if (instance->offset_row + instance->screen_rows / 2 <=
520 instance->rows - instance->screen_rows)
521 instance->offset_row += instance->screen_rows / 2;
[7ddc2c7]522 else
[888c06e]523 instance->offset_row = instance->rows - instance->screen_rows;
[a35b458]524
[7ddc2c7]525 fb_redraw_internal(instance);
526 cursor_put(instance);
[a35b458]527
[7ddc2c7]528 spinlock_unlock(&instance->lock);
[76fca31]529}
530
[a71c158]531/** Refresh the screen
532 *
533 */
534static void fb_redraw(outdev_t *dev)
535{
536 fb_instance_t *instance = (fb_instance_t *) dev->data;
[a35b458]537
[c263c77]538 spinlock_lock(&instance->lock);
[a71c158]539 fb_redraw_internal(instance);
[c263c77]540 spinlock_unlock(&instance->lock);
[a71c158]541}
[76fca31]542
[e037cf37]543/** Framebuffer was mapped or unmapped.
544 *
545 * @param arg Framebuffer instance
546 */
547static void fb_mapped_changed(void *arg)
548{
549 fb_instance_t *instance = (fb_instance_t *) arg;
550
551 if (!instance->parea.mapped) {
552 spinlock_lock(&instance->lock);
553 fb_redraw_internal(instance);
554 spinlock_unlock(&instance->lock);
555 }
556}
557
[a0e1b48]558/** Initialize framebuffer as a output character device
[76fca31]559 *
[bbf5657]560 */
[a71c158]561outdev_t *fb_init(fb_properties_t *props)
[bbf5657]562{
[63e27ef]563 assert(props);
564 assert(props->x > 0);
565 assert(props->y > 0);
566 assert(props->scan > 0);
[a35b458]567
[a71c158]568 rgb_conv_t rgb_conv;
569 unsigned int pixelbytes;
[a35b458]570
[965dc18]571 switch (props->visual) {
[2bc137c2]572 case VISUAL_INDIRECT_8:
[30885b9]573 rgb_conv = bgr_323;
[d6f270f]574 pixelbytes = 1;
575 break;
[19490ce]576 case VISUAL_RGB_5_5_5_LE:
577 rgb_conv = rgb_555_le;
578 pixelbytes = 2;
579 break;
580 case VISUAL_RGB_5_5_5_BE:
581 rgb_conv = rgb_555_be;
582 pixelbytes = 2;
583 break;
584 case VISUAL_RGB_5_6_5_LE:
585 rgb_conv = rgb_565_le;
[2bc137c2]586 pixelbytes = 2;
587 break;
[19490ce]588 case VISUAL_RGB_5_6_5_BE:
589 rgb_conv = rgb_565_be;
[d6f270f]590 pixelbytes = 2;
591 break;
[2bc137c2]592 case VISUAL_RGB_8_8_8:
[76fca31]593 rgb_conv = rgb_888;
[2bc137c2]594 pixelbytes = 3;
595 break;
[95b9963]596 case VISUAL_BGR_8_8_8:
597 rgb_conv = bgr_888;
598 pixelbytes = 3;
599 break;
[2bc137c2]600 case VISUAL_RGB_8_8_8_0:
[6ac14a70]601 rgb_conv = rgb_8880;
[2bc137c2]602 pixelbytes = 4;
[d6f270f]603 break;
[2bc137c2]604 case VISUAL_RGB_0_8_8_8:
[76fca31]605 rgb_conv = rgb_0888;
[d6f270f]606 pixelbytes = 4;
607 break;
[ccb0cbc]608 case VISUAL_BGR_0_8_8_8:
[76fca31]609 rgb_conv = bgr_0888;
[ccb0cbc]610 pixelbytes = 4;
611 break;
[30885b9]612 case VISUAL_BGR_8_8_8_0:
613 rgb_conv = bgr_8880;
614 pixelbytes = 4;
615 break;
[d6f270f]616 default:
[00a020d]617 LOG("Unsupported visual.");
[a71c158]618 return NULL;
[fcbca14f]619 }
[a35b458]620
[11b285d]621 outdev_t *fbdev = malloc(sizeof(outdev_t));
[a71c158]622 if (!fbdev)
623 return NULL;
[a35b458]624
[11b285d]625 fb_instance_t *instance = malloc(sizeof(fb_instance_t));
[a71c158]626 if (!instance) {
627 free(fbdev);
628 return NULL;
629 }
[a35b458]630
[a71c158]631 outdev_initialize("fbdev", fbdev, &fbdev_ops);
632 fbdev->data = instance;
[a35b458]633
[c263c77]634 spinlock_initialize(&instance->lock, "*fb.instance.lock");
[a35b458]635
[a71c158]636 instance->rgb_conv = rgb_conv;
637 instance->pixelbytes = pixelbytes;
638 instance->xres = props->x;
639 instance->yres = props->y;
640 instance->scanline = props->scan;
[a35b458]641
[888c06e]642 instance->screen_rows = Y2ROW(instance->yres);
[a35b458]643
[a71c158]644 instance->cols = X2COL(instance->xres);
[888c06e]645 instance->rows = FB_PAGES * instance->screen_rows;
[a35b458]646
[888c06e]647 instance->start_row = instance->rows - instance->screen_rows;
[7ddc2c7]648 instance->offset_row = instance->start_row;
[888c06e]649 instance->row = instance->start_row;
650 instance->column = 0;
[a35b458]651
[a71c158]652 instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
653 instance->glyphbytes = ROW2Y(instance->glyphscanline);
654 instance->bgscanbytes = instance->xres * instance->pixelbytes;
[a35b458]655
[a71c158]656 size_t fbsize = instance->scanline * instance->yres;
657 size_t bbsize = instance->cols * instance->rows * sizeof(uint16_t);
658 size_t glyphsize = FONT_GLYPHS * instance->glyphbytes;
[a35b458]659
[adec5b45]660 instance->addr = (uint8_t *) km_map((uintptr_t) props->addr, fbsize,
[de96d3b]661 KM_NATURAL_ALIGNMENT, PAGE_WRITE | PAGE_WRITE_COMBINE);
[a71c158]662 if (!instance->addr) {
[00a020d]663 LOG("Unable to map framebuffer.");
[a71c158]664 free(instance);
665 free(fbdev);
666 return NULL;
[00a020d]667 }
[a35b458]668
[11b285d]669 instance->backbuf = (uint16_t *) malloc(bbsize);
[a71c158]670 if (!instance->backbuf) {
[00a020d]671 LOG("Unable to allocate backbuffer.");
[a71c158]672 free(instance);
673 free(fbdev);
674 return NULL;
[00a020d]675 }
[a35b458]676
[11b285d]677 instance->glyphs = (uint8_t *) malloc(glyphsize);
[a71c158]678 if (!instance->glyphs) {
[00a020d]679 LOG("Unable to allocate glyphs.");
[a71c158]680 free(instance->backbuf);
681 free(instance);
682 free(fbdev);
683 return NULL;
[00a020d]684 }
[a35b458]685
[11b285d]686 instance->bgscan = malloc(instance->bgscanbytes);
[a71c158]687 if (!instance->bgscan) {
[00a020d]688 LOG("Unable to allocate background pixel.");
[a71c158]689 free(instance->glyphs);
690 free(instance->backbuf);
691 free(instance);
692 free(fbdev);
693 return NULL;
[00a020d]694 }
[a35b458]695
[a71c158]696 memsetw(instance->backbuf, instance->cols * instance->rows, 0);
697 glyphs_render(instance);
[a35b458]698
[6f7071b]699 ddi_parea_init(&instance->parea);
[b366a6f4]700 instance->parea.pbase = props->addr;
701 instance->parea.frames = SIZE2FRAMES(fbsize);
702 instance->parea.unpriv = false;
703 instance->parea.mapped = false;
[e037cf37]704 instance->parea.mapped_changed = fb_mapped_changed;
705 instance->parea.arg = (void *) instance;
[b366a6f4]706 ddi_parea_register(&instance->parea);
[a35b458]707
[a71c158]708 if (!fb_exported) {
709 /*
[b366a6f4]710 * We export the kernel framebuffer for uspace usage.
711 * This is used in the case the uspace framebuffer
712 * driver is not self-sufficient.
[a71c158]713 */
714 sysinfo_set_item_val("fb", NULL, true);
715 sysinfo_set_item_val("fb.kind", NULL, 1);
716 sysinfo_set_item_val("fb.width", NULL, instance->xres);
717 sysinfo_set_item_val("fb.height", NULL, instance->yres);
718 sysinfo_set_item_val("fb.scanline", NULL, instance->scanline);
719 sysinfo_set_item_val("fb.visual", NULL, props->visual);
720 sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
[a35b458]721
[a71c158]722 fb_exported = true;
723 }
[a35b458]724
[a71c158]725 fb_redraw(fbdev);
726 return fbdev;
[bbf5657]727}
[b45c443]728
[94d614e]729/** @}
[b45c443]730 */
Note: See TracBrowser for help on using the repository browser.