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

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

Print "\t" properly on framebuffers where number of columns is not divisible by 8.

  • Property mode set to 100644
File size: 16.9 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
[76fca31]30/** @addtogroup genarch
[b45c443]31 * @{
32 */
33/** @file
34 */
35
[fe050b7]36#include <genarch/fb/font-8x16.h>
[6e71a9d8]37#include <genarch/fb/logo-196x66.h>
[fe050b7]38#include <genarch/fb/fb.h>
[bbf5657]39#include <console/chardev.h>
40#include <console/console.h>
[2666daa]41#include <sysinfo/sysinfo.h>
[d4673296]42#include <mm/km.h>
[74d1d66]43#include <mm/slab.h>
[76fca31]44#include <align.h>
[fcbca14f]45#include <panic.h>
[d87c3f3]46#include <memstr.h>
[74d1d66]47#include <config.h>
[6eb96fce]48#include <bitops.h>
49#include <print.h>
[19f857a]50#include <str.h>
[f8ddd17]51#include <ddi/ddi.h>
[d99c1d2]52#include <typedefs.h>
[30885b9]53#include <byteorder.h>
[bbf5657]54
[a71c158]55#define BG_COLOR 0x000080
56#define FG_COLOR 0xffff00
57#define INV_COLOR 0xaaaaaa
[6e71a9d8]58
[a71c158]59#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
60#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
61#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
[76fca31]62
[a71c158]63#define COL2X(col) ((col) * FONT_WIDTH)
64#define ROW2Y(row) ((row) * FONT_SCANLINES)
[bbf5657]65
[a71c158]66#define X2COL(x) ((x) / FONT_WIDTH)
67#define Y2ROW(y) ((y) / FONT_SCANLINES)
[bbf5657]68
[a71c158]69#define FB_POS(instance, x, y) \
70 ((y) * (instance)->scanline + (x) * (instance)->pixelbytes)
[a2c4445]71
[a71c158]72#define BB_POS(instance, col, row) \
73 ((row) * (instance)->cols + (col))
[a2c4445]74
[a71c158]75#define GLYPH_POS(instance, glyph, y) \
76 ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
[95c7526]77
[a71c158]78typedef void (* rgb_conv_t)(void *, uint32_t);
[bbf5657]79
[a71c158]80typedef struct {
[c263c77]81 SPINLOCK_DECLARE(lock);
[a71c158]82
[b366a6f4]83 parea_t parea;
84
[a71c158]85 uint8_t *addr;
86 uint16_t *backbuf;
87 uint8_t *glyphs;
88 uint8_t *bgscan;
89
90 rgb_conv_t rgb_conv;
91
92 unsigned int xres;
93 unsigned int yres;
94
95 unsigned int ylogo;
96 unsigned int ytrim;
97 unsigned int rowtrim;
98
99 unsigned int scanline;
100 unsigned int glyphscanline;
101
102 unsigned int pixelbytes;
103 unsigned int glyphbytes;
104 unsigned int bgscanbytes;
105
106 unsigned int cols;
107 unsigned int rows;
108
109 unsigned int position;
110} fb_instance_t;
[fcbca14f]111
[b366a6f4]112static void fb_putchar(outdev_t *dev, wchar_t ch);
[a71c158]113static void fb_redraw_internal(fb_instance_t *instance);
114static void fb_redraw(outdev_t *dev);
[253f35a1]115
[a71c158]116static outdev_operations_t fbdev_ops = {
117 .write = fb_putchar,
118 .redraw = fb_redraw
119};
[95c7526]120
[30885b9]121/*
122 * RGB conversion functions.
[76fca31]123 *
[30885b9]124 * These functions write an RGB value to some memory in some predefined format.
125 * The naming convention corresponds to the format created by these functions.
126 * The functions use the so called network order (i.e. big endian) with respect
127 * to their names.
[76fca31]128 */
[30885b9]129
[76fca31]130static void rgb_0888(void *dst, uint32_t rgb)
[ccb0cbc]131{
[30885b9]132 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
133 (RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
[ccb0cbc]134}
135
[76fca31]136static void bgr_0888(void *dst, uint32_t rgb)
[ccb0cbc]137{
[30885b9]138 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
139 (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
[ccb0cbc]140}
141
[6ac14a70]142static void rgb_8880(void *dst, uint32_t rgb)
143{
[30885b9]144 *((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
145 (GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
[6ac14a70]146}
147
[30885b9]148static void bgr_8880(void *dst, uint32_t rgb)
149{
150 *((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
151 (GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
152}
[76fca31]153
154static void rgb_888(void *dst, uint32_t rgb)
[fcbca14f]155{
[30885b9]156 ((uint8_t *) dst)[0] = RED(rgb, 8);
[6e71a9d8]157 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
[30885b9]158 ((uint8_t *) dst)[2] = BLUE(rgb, 8);
[95b9963]159}
160
161static void bgr_888(void *dst, uint32_t rgb)
162{
[30885b9]163 ((uint8_t *) dst)[0] = BLUE(rgb, 8);
[95b9963]164 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
[30885b9]165 ((uint8_t *) dst)[2] = RED(rgb, 8);
[fcbca14f]166}
167
[19490ce]168static void rgb_555_be(void *dst, uint32_t rgb)
[2bc137c2]169{
[19490ce]170 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
171 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
[2bc137c2]172}
173
[19490ce]174static void rgb_555_le(void *dst, uint32_t rgb)
[fcbca14f]175{
[19490ce]176 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
177 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
178}
179
180static void rgb_565_be(void *dst, uint32_t rgb)
181{
182 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
183 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
184}
185
186static void rgb_565_le(void *dst, uint32_t rgb)
187{
188 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
189 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
[fcbca14f]190}
191
[30885b9]192/** BGR 3:2:3
[b4fa652]193 *
194 * Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
195 * will most likely use a color palette. The color appearance
196 * will be pretty random and depend on the default installed
197 * palette. This could be fixed by supporting custom palette
198 * and setting it to simulate the 8-bit truecolor.
[925fdd7]199 *
[a71c158]200 * Currently we set the palette on the ia32, amd64, ppc32 and sparc64 port.
[925fdd7]201 *
202 * Note that the byte is being inverted by this function. The reason is
203 * that we would like to use a color palette where the white color code
[882d7a8]204 * is 0 and the black color code is 255, as some machines (Sun Blade 1500)
[925fdd7]205 * use these codes for black and white and prevent to set codes
206 * 0 and 255 to other colors.
[882d7a8]207 *
[b4fa652]208 */
[30885b9]209static void bgr_323(void *dst, uint32_t rgb)
[fcbca14f]210{
[76fca31]211 *((uint8_t *) dst)
212 = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
[fcbca14f]213}
214
[6e71a9d8]215/** Hide logo and refresh screen
216 *
217 */
[b366a6f4]218static void logo_hide(fb_instance_t *instance)
[6e71a9d8]219{
[a71c158]220 instance->ylogo = 0;
221 instance->ytrim = instance->yres;
222 instance->rowtrim = instance->rows;
223
[b366a6f4]224 if ((!instance->parea.mapped) || (console_override))
[a71c158]225 fb_redraw_internal(instance);
[6e71a9d8]226}
227
[76fca31]228/** Draw character at given position
[b4fa652]229 *
230 */
[a71c158]231static void glyph_draw(fb_instance_t *instance, uint16_t glyph,
[b366a6f4]232 unsigned int col, unsigned int row, bool overlay)
[bbf5657]233{
[76fca31]234 unsigned int x = COL2X(col);
235 unsigned int y = ROW2Y(row);
236 unsigned int yd;
237
[a71c158]238 if (y >= instance->ytrim)
[b366a6f4]239 logo_hide(instance);
[6e71a9d8]240
[c8bf88d]241 if (!overlay)
[a71c158]242 instance->backbuf[BB_POS(instance, col, row)] = glyph;
[76fca31]243
[b366a6f4]244 if ((!instance->parea.mapped) || (console_override)) {
[516ff92]245 for (yd = 0; yd < FONT_SCANLINES; yd++)
[a71c158]246 memcpy(&instance->addr[FB_POS(instance, x, y + yd + instance->ylogo)],
247 &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
248 instance->glyphscanline);
[516ff92]249 }
[bbf5657]250}
251
[76fca31]252/** Scroll screen down by one row
253 *
254 *
255 */
[b366a6f4]256static void screen_scroll(fb_instance_t *instance)
[bbf5657]257{
[a71c158]258 if (instance->ylogo > 0) {
[b366a6f4]259 logo_hide(instance);
[6c0adbc]260 return;
261 }
[6e71a9d8]262
[b366a6f4]263 if ((!instance->parea.mapped) || (console_override)) {
[516ff92]264 unsigned int row;
[730376d]265
[a71c158]266 for (row = 0; row < instance->rows; row++) {
[516ff92]267 unsigned int y = ROW2Y(row);
268 unsigned int yd;
[76fca31]269
[516ff92]270 for (yd = 0; yd < FONT_SCANLINES; yd++) {
271 unsigned int x;
272 unsigned int col;
[76fca31]273
[a71c158]274 for (col = 0, x = 0; col < instance->cols;
275 col++, x += FONT_WIDTH) {
[dcdc31d]276 uint16_t glyph;
[76fca31]277
[a71c158]278 if (row < instance->rows - 1) {
279 if (instance->backbuf[BB_POS(instance, col, row)] ==
280 instance->backbuf[BB_POS(instance, col, row + 1)])
[516ff92]281 continue;
282
[a71c158]283 glyph = instance->backbuf[BB_POS(instance, col, row + 1)];
[516ff92]284 } else
285 glyph = 0;
286
[a71c158]287 memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
288 &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
289 instance->glyphscanline);
[516ff92]290 }
[76fca31]291 }
[51baa8a]292 }
[6eb96fce]293 }
[76fca31]294
[a71c158]295 memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)],
296 instance->cols * (instance->rows - 1) * sizeof(uint16_t));
297 memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
298 instance->cols, 0);
[a2c4445]299}
300
[b366a6f4]301static void cursor_put(fb_instance_t *instance)
[bbf5657]302{
[a71c158]303 unsigned int col = instance->position % instance->cols;
304 unsigned int row = instance->position / instance->cols;
[c8bf88d]305
[b366a6f4]306 glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
[bbf5657]307}
308
[b366a6f4]309static void cursor_remove(fb_instance_t *instance)
[bbf5657]310{
[a71c158]311 unsigned int col = instance->position % instance->cols;
312 unsigned int row = instance->position / instance->cols;
[c8bf88d]313
[a71c158]314 glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
[b366a6f4]315 col, row, true);
[bbf5657]316}
317
[76fca31]318/** Render glyphs
319 *
320 * Convert glyphs from device independent font
321 * description to current visual representation.
322 *
323 */
[a71c158]324static void glyphs_render(fb_instance_t *instance)
[76fca31]325{
[6e71a9d8]326 /* Prerender glyphs */
[dcdc31d]327 uint16_t glyph;
[76fca31]328
329 for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
[98895c5c]330 uint32_t fg_color;
331
332 if (glyph == FONT_GLYPHS - 1)
333 fg_color = INV_COLOR;
334 else
335 fg_color = FG_COLOR;
336
[76fca31]337 unsigned int y;
338
339 for (y = 0; y < FONT_SCANLINES; y++) {
340 unsigned int x;
341
[edf5774]342 for (x = 0; x < FONT_WIDTH; x++) {
[a71c158]343 void *dst =
344 &instance->glyphs[GLYPH_POS(instance, glyph, y) +
345 x * instance->pixelbytes];
[dcdc31d]346 uint32_t rgb = (fb_font[glyph][y] &
[98895c5c]347 (1 << (7 - x))) ? fg_color : BG_COLOR;
[a71c158]348 instance->rgb_conv(dst, rgb);
[edf5774]349 }
[76fca31]350 }
351 }
352
[6e71a9d8]353 /* Prerender background scanline */
354 unsigned int x;
355
[a71c158]356 for (x = 0; x < instance->xres; x++)
357 instance->rgb_conv(&instance->bgscan[x * instance->pixelbytes], BG_COLOR);
[76fca31]358}
359
[a71c158]360/** Print character to screen
361 *
362 * Emulate basic terminal commands.
[76fca31]363 *
364 */
[b366a6f4]365static void fb_putchar(outdev_t *dev, wchar_t ch)
[76fca31]366{
[a71c158]367 fb_instance_t *instance = (fb_instance_t *) dev->data;
[c263c77]368 spinlock_lock(&instance->lock);
[a71c158]369
370 switch (ch) {
371 case '\n':
[b366a6f4]372 cursor_remove(instance);
[a71c158]373 instance->position += instance->cols;
374 instance->position -= instance->position % instance->cols;
375 break;
376 case '\r':
[b366a6f4]377 cursor_remove(instance);
[a71c158]378 instance->position -= instance->position % instance->cols;
379 break;
380 case '\b':
[b366a6f4]381 cursor_remove(instance);
[a71c158]382 if (instance->position % instance->cols)
383 instance->position--;
384 break;
385 case '\t':
[b366a6f4]386 cursor_remove(instance);
[a71c158]387 do {
388 glyph_draw(instance, fb_font_glyph(' '),
389 instance->position % instance->cols,
[b366a6f4]390 instance->position / instance->cols, false);
[a71c158]391 instance->position++;
[f061e404]392 } while (((instance->position % instance->cols) % 8 != 0) &&
393 (instance->position < instance->cols * instance->rows));
[a71c158]394 break;
395 default:
396 glyph_draw(instance, fb_font_glyph(ch),
397 instance->position % instance->cols,
[b366a6f4]398 instance->position / instance->cols, false);
[a71c158]399 instance->position++;
400 }
401
402 if (instance->position >= instance->cols * instance->rows) {
403 instance->position -= instance->cols;
[b366a6f4]404 screen_scroll(instance);
[a71c158]405 }
406
[b366a6f4]407 cursor_put(instance);
[a71c158]408
[c263c77]409 spinlock_unlock(&instance->lock);
[a71c158]410}
411
412static void fb_redraw_internal(fb_instance_t *instance)
413{
414 if (instance->ylogo > 0) {
[6e71a9d8]415 unsigned int y;
416
417 for (y = 0; y < LOGO_HEIGHT; y++) {
418 unsigned int x;
419
[a71c158]420 for (x = 0; x < instance->xres; x++)
421 instance->rgb_conv(&instance->addr[FB_POS(instance, x, y)],
[edf5774]422 (x < LOGO_WIDTH) ?
423 fb_logo[y * LOGO_WIDTH + x] :
424 LOGO_COLOR);
[6e71a9d8]425 }
426 }
427
[76fca31]428 unsigned int row;
429
[a71c158]430 for (row = 0; row < instance->rowtrim; row++) {
431 unsigned int y = instance->ylogo + ROW2Y(row);
[76fca31]432 unsigned int yd;
433
434 for (yd = 0; yd < FONT_SCANLINES; yd++) {
435 unsigned int x;
436 unsigned int col;
437
[a71c158]438 for (col = 0, x = 0; col < instance->cols;
[edf5774]439 col++, x += FONT_WIDTH) {
[a71c158]440 uint16_t glyph =
441 instance->backbuf[BB_POS(instance, col, row)];
442 void *dst = &instance->addr[FB_POS(instance, x, y + yd)];
443 void *src = &instance->glyphs[GLYPH_POS(instance, glyph, yd)];
444 memcpy(dst, src, instance->glyphscanline);
[edf5774]445 }
[76fca31]446 }
447 }
448
[a71c158]449 if (COL2X(instance->cols) < instance->xres) {
[76fca31]450 unsigned int y;
[a71c158]451 unsigned int size =
452 (instance->xres - COL2X(instance->cols)) * instance->pixelbytes;
[76fca31]453
[a71c158]454 for (y = instance->ylogo; y < instance->yres; y++)
455 memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)],
456 instance->bgscan, size);
[76fca31]457 }
458
[a71c158]459 if (ROW2Y(instance->rowtrim) + instance->ylogo < instance->yres) {
[76fca31]460 unsigned int y;
461
[a71c158]462 for (y = ROW2Y(instance->rowtrim) + instance->ylogo;
463 y < instance->yres; y++)
464 memcpy(&instance->addr[FB_POS(instance, 0, y)],
465 instance->bgscan, instance->bgscanbytes);
[76fca31]466 }
467}
468
[a71c158]469/** Refresh the screen
470 *
471 */
472static void fb_redraw(outdev_t *dev)
473{
474 fb_instance_t *instance = (fb_instance_t *) dev->data;
475
[c263c77]476 spinlock_lock(&instance->lock);
[a71c158]477 fb_redraw_internal(instance);
[c263c77]478 spinlock_unlock(&instance->lock);
[a71c158]479}
[76fca31]480
[a0e1b48]481/** Initialize framebuffer as a output character device
[76fca31]482 *
[bbf5657]483 */
[a71c158]484outdev_t *fb_init(fb_properties_t *props)
[bbf5657]485{
[00a020d]486 ASSERT(props);
487 ASSERT(props->x > 0);
488 ASSERT(props->y > 0);
489 ASSERT(props->scan > 0);
490
[a71c158]491 rgb_conv_t rgb_conv;
492 unsigned int pixelbytes;
493
[965dc18]494 switch (props->visual) {
[2bc137c2]495 case VISUAL_INDIRECT_8:
[30885b9]496 rgb_conv = bgr_323;
[d6f270f]497 pixelbytes = 1;
498 break;
[19490ce]499 case VISUAL_RGB_5_5_5_LE:
500 rgb_conv = rgb_555_le;
501 pixelbytes = 2;
502 break;
503 case VISUAL_RGB_5_5_5_BE:
504 rgb_conv = rgb_555_be;
505 pixelbytes = 2;
506 break;
507 case VISUAL_RGB_5_6_5_LE:
508 rgb_conv = rgb_565_le;
[2bc137c2]509 pixelbytes = 2;
510 break;
[19490ce]511 case VISUAL_RGB_5_6_5_BE:
512 rgb_conv = rgb_565_be;
[d6f270f]513 pixelbytes = 2;
514 break;
[2bc137c2]515 case VISUAL_RGB_8_8_8:
[76fca31]516 rgb_conv = rgb_888;
[2bc137c2]517 pixelbytes = 3;
518 break;
[95b9963]519 case VISUAL_BGR_8_8_8:
520 rgb_conv = bgr_888;
521 pixelbytes = 3;
522 break;
[2bc137c2]523 case VISUAL_RGB_8_8_8_0:
[6ac14a70]524 rgb_conv = rgb_8880;
[2bc137c2]525 pixelbytes = 4;
[d6f270f]526 break;
[2bc137c2]527 case VISUAL_RGB_0_8_8_8:
[76fca31]528 rgb_conv = rgb_0888;
[d6f270f]529 pixelbytes = 4;
530 break;
[ccb0cbc]531 case VISUAL_BGR_0_8_8_8:
[76fca31]532 rgb_conv = bgr_0888;
[ccb0cbc]533 pixelbytes = 4;
534 break;
[30885b9]535 case VISUAL_BGR_8_8_8_0:
536 rgb_conv = bgr_8880;
537 pixelbytes = 4;
538 break;
[d6f270f]539 default:
[00a020d]540 LOG("Unsupported visual.");
[a71c158]541 return NULL;
[fcbca14f]542 }
[8424198]543
[a71c158]544 outdev_t *fbdev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
545 if (!fbdev)
546 return NULL;
[bbf5657]547
[a71c158]548 fb_instance_t *instance = malloc(sizeof(fb_instance_t), FRAME_ATOMIC);
549 if (!instance) {
550 free(fbdev);
551 return NULL;
552 }
[6e71a9d8]553
[a71c158]554 outdev_initialize("fbdev", fbdev, &fbdev_ops);
555 fbdev->data = instance;
556
[c263c77]557 spinlock_initialize(&instance->lock, "*fb.instance.lock");
[b366a6f4]558
[a71c158]559 instance->rgb_conv = rgb_conv;
560 instance->pixelbytes = pixelbytes;
561 instance->xres = props->x;
562 instance->yres = props->y;
563 instance->scanline = props->scan;
564 instance->position = 0;
565
566 instance->cols = X2COL(instance->xres);
567 instance->rows = Y2ROW(instance->yres);
568
569 if (instance->yres > LOGO_HEIGHT) {
570 instance->ylogo = LOGO_HEIGHT;
571 instance->rowtrim = instance->rows - Y2ROW(instance->ylogo);
572 if (instance->ylogo % FONT_SCANLINES > 0)
573 instance->rowtrim--;
574 instance->ytrim = ROW2Y(instance->rowtrim);
[6e71a9d8]575 } else {
[a71c158]576 instance->ylogo = 0;
577 instance->ytrim = instance->yres;
578 instance->rowtrim = instance->rows;
[6e71a9d8]579 }
[76fca31]580
[a71c158]581 instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
582 instance->glyphbytes = ROW2Y(instance->glyphscanline);
583 instance->bgscanbytes = instance->xres * instance->pixelbytes;
[76fca31]584
[a71c158]585 size_t fbsize = instance->scanline * instance->yres;
586 size_t bbsize = instance->cols * instance->rows * sizeof(uint16_t);
587 size_t glyphsize = FONT_GLYPHS * instance->glyphbytes;
[76fca31]588
[adec5b45]589 instance->addr = (uint8_t *) km_map((uintptr_t) props->addr, fbsize,
590 PAGE_WRITE | PAGE_NOT_CACHEABLE);
[a71c158]591 if (!instance->addr) {
[00a020d]592 LOG("Unable to map framebuffer.");
[a71c158]593 free(instance);
594 free(fbdev);
595 return NULL;
[00a020d]596 }
597
[a71c158]598 instance->backbuf = (uint16_t *) malloc(bbsize, 0);
599 if (!instance->backbuf) {
[00a020d]600 LOG("Unable to allocate backbuffer.");
[a71c158]601 free(instance);
602 free(fbdev);
603 return NULL;
[00a020d]604 }
[76fca31]605
[a71c158]606 instance->glyphs = (uint8_t *) malloc(glyphsize, 0);
607 if (!instance->glyphs) {
[00a020d]608 LOG("Unable to allocate glyphs.");
[a71c158]609 free(instance->backbuf);
610 free(instance);
611 free(fbdev);
612 return NULL;
[00a020d]613 }
[76fca31]614
[a71c158]615 instance->bgscan = malloc(instance->bgscanbytes, 0);
616 if (!instance->bgscan) {
[00a020d]617 LOG("Unable to allocate background pixel.");
[a71c158]618 free(instance->glyphs);
619 free(instance->backbuf);
620 free(instance);
621 free(fbdev);
622 return NULL;
[00a020d]623 }
[76fca31]624
[a71c158]625 memsetw(instance->backbuf, instance->cols * instance->rows, 0);
626 glyphs_render(instance);
627
[b366a6f4]628 link_initialize(&instance->parea.link);
629 instance->parea.pbase = props->addr;
630 instance->parea.frames = SIZE2FRAMES(fbsize);
631 instance->parea.unpriv = false;
632 instance->parea.mapped = false;
633 ddi_parea_register(&instance->parea);
634
[a71c158]635 if (!fb_exported) {
636 /*
[b366a6f4]637 * We export the kernel framebuffer for uspace usage.
638 * This is used in the case the uspace framebuffer
639 * driver is not self-sufficient.
[a71c158]640 */
641 sysinfo_set_item_val("fb", NULL, true);
642 sysinfo_set_item_val("fb.kind", NULL, 1);
643 sysinfo_set_item_val("fb.width", NULL, instance->xres);
644 sysinfo_set_item_val("fb.height", NULL, instance->yres);
645 sysinfo_set_item_val("fb.scanline", NULL, instance->scanline);
646 sysinfo_set_item_val("fb.visual", NULL, props->visual);
647 sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
648
649 fb_exported = true;
650 }
[00a020d]651
[a71c158]652 fb_redraw(fbdev);
653 return fbdev;
[bbf5657]654}
[b45c443]655
[94d614e]656/** @}
[b45c443]657 */
Note: See TracBrowser for help on using the repository browser.