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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f64e81a was ba7371f9, checked in by Martin Decky <martin@…>, 16 years ago

rename spinlocks to be more descriptive

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