source: mainline/uspace/srv/hid/output/port/kfb.c@ c8ea6eca

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

Improve Doxygen documentaion

This is stil WiP. A number of libraries, drivers and services were
converted to using a more hierarchical and decentralized scheme when it
comes to specifying to which doxygen group they belong.

  • Property mode set to 100644
File size: 20.1 KB
Line 
1/*
2 * Copyright (c) 2008 Martin Decky
3 * Copyright (c) 2006 Jakub Vana
4 * Copyright (c) 2006 Ondrej Palkovsky
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/** @addtogroup output
32 * @{
33 */
34
35#include <abi/fb/visuals.h>
36#include <sys/types.h>
37#include <inttypes.h>
38#include <screenbuffer.h>
39#include <imgmap.h>
40#include <errno.h>
41#include <bool.h>
42#include <sysinfo.h>
43#include <ddi.h>
44#include <stdlib.h>
45#include <mem.h>
46#include <as.h>
47#include <align.h>
48#include "../gfx/font-8x16.h"
49#include "../fb.h"
50#include "kfb.h"
51
52#define DEFAULT_BGCOLOR 0xffffff
53#define DEFAULT_FGCOLOR 0x000000
54
55#define FB_POS(x, y) ((y) * kfb.scanline + (x) * kfb.pixel_bytes)
56
57#define COL2X(col) ((col) * FONT_WIDTH)
58#define ROW2Y(row) ((row) * FONT_SCANLINES)
59#define X2COL(x) ((x) / FONT_WIDTH)
60#define Y2ROW(y) ((y) / FONT_SCANLINES)
61
62#define GLYPH_POS(glyph, y, inverted) \
63 (((glyph) + (inverted) * FONT_GLYPHS) * (kfb.glyph_bytes) + (y) * (kfb.glyph_scanline))
64
65#define POINTER_WIDTH 11
66#define POINTER_HEIGHT 18
67
68static uint8_t pointer[] = {
69 0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x11, 0x00, 0x21, 0x00,
70 0x41, 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x04, 0x01, 0x03,
71 0x81, 0x00, 0x89, 0x00, 0x15, 0x01, 0x23, 0x01, 0x21, 0x01, 0xc0, 0x00
72};
73
74static uint8_t pointer_mask[] = {
75 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00,
76 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0xff, 0x03,
77 0xff, 0x00, 0xff, 0x00, 0xf7, 0x01, 0xe3, 0x01, 0xe1, 0x01, 0xc0, 0x00
78};
79
80/** Function to draw a character. */
81typedef void (*draw_char_t)(sysarg_t, sysarg_t, bool, wchar_t, pixel_t,
82 pixel_t);
83
84typedef struct {
85 sysarg_t width;
86 sysarg_t height;
87 size_t offset;
88 size_t scanline;
89 visual_t visual;
90
91 size_t size;
92 uint8_t *addr;
93
94 pixel2visual_t pixel2visual;
95 visual2pixel_t visual2pixel;
96 visual_mask_t visual_mask;
97 size_t pixel_bytes;
98
99 sysarg_t pointer_x;
100 sysarg_t pointer_y;
101 bool pointer_visible;
102 imgmap_t *pointer_imgmap;
103
104 /*
105 * Pre-rendered mask for rendering
106 * glyphs. Specific for the framebuffer
107 * visual.
108 */
109
110 size_t glyph_scanline;
111 size_t glyph_bytes;
112 uint8_t *glyphs;
113
114 uint8_t *backbuf;
115} kfb_t;
116
117typedef struct {
118 /**
119 * Character drawing function for this viewport.
120 * Different viewports might use different drawing
121 * functions depending on whether their scanlines
122 * are aligned on a word boundary.
123 */
124 draw_char_t draw_char;
125} kfb_vp_t;
126
127static kfb_t kfb;
128
129static pixel_t color_table[16] = {
130 [COLOR_BLACK] = 0x000000,
131 [COLOR_BLUE] = 0x0000f0,
132 [COLOR_GREEN] = 0x00f000,
133 [COLOR_CYAN] = 0x00f0f0,
134 [COLOR_RED] = 0xf00000,
135 [COLOR_MAGENTA] = 0xf000f0,
136 [COLOR_YELLOW] = 0xf0f000,
137 [COLOR_WHITE] = 0xf0f0f0,
138
139 [COLOR_BLACK + 8] = 0x000000,
140 [COLOR_BLUE + 8] = 0x0000ff,
141 [COLOR_GREEN + 8] = 0x00ff00,
142 [COLOR_CYAN + 8] = 0x00ffff,
143 [COLOR_RED + 8] = 0xff0000,
144 [COLOR_MAGENTA + 8] = 0xff00ff,
145 [COLOR_YELLOW + 8] = 0xffff00,
146 [COLOR_WHITE + 8] = 0xffffff,
147};
148
149static void put_pixel(sysarg_t x, sysarg_t y, pixel_t pixel)
150{
151 if ((x >= kfb.width) || (y >= kfb.height))
152 return;
153
154 kfb.pixel2visual(kfb.addr + FB_POS(x, y), pixel);
155}
156
157static pixel_t get_pixel(sysarg_t x, sysarg_t y)
158{
159 if ((x >= kfb.width) || (y >= kfb.height))
160 return 0;
161
162 return kfb.visual2pixel(kfb.addr + FB_POS(x, y));
163}
164
165static void pointer_show(void)
166{
167 if (kfb.pointer_visible) {
168 for (sysarg_t y = 0; y < POINTER_HEIGHT; y++) {
169 for (sysarg_t x = 0; x < POINTER_WIDTH; x++) {
170 sysarg_t dx = kfb.pointer_x + x;
171 sysarg_t dy = kfb.pointer_y + y;
172
173 pixel_t pixel = get_pixel(dx, dy);
174 imgmap_put_pixel(kfb.pointer_imgmap, x, y, pixel);
175
176 size_t offset = y * ((POINTER_WIDTH - 1) / 8 + 1) + x / 8;
177 bool visible = pointer_mask[offset] & (1 << (x % 8));
178
179 if (visible) {
180 pixel = (pointer[offset] & (1 << (x % 8))) ?
181 0x000000 : 0xffffff;
182 put_pixel(dx, dy, pixel);
183 }
184 }
185 }
186 }
187}
188
189static void pointer_hide(void)
190{
191 if (kfb.pointer_visible) {
192 for (sysarg_t y = 0; y < POINTER_HEIGHT; y++) {
193 for (sysarg_t x = 0; x < POINTER_WIDTH; x++) {
194 sysarg_t dx = kfb.pointer_x + x;
195 sysarg_t dy = kfb.pointer_y + y;
196
197 pixel_t pixel =
198 imgmap_get_pixel(kfb.pointer_imgmap, x, y);
199 put_pixel(dx, dy, pixel);
200 }
201 }
202 }
203}
204
205/** Draw a filled rectangle.
206 *
207 */
208static void draw_filled_rect(sysarg_t x1, sysarg_t y1, sysarg_t x2, sysarg_t y2,
209 pixel_t color)
210{
211 if ((y1 >= y2) || (x1 >= x2))
212 return;
213
214 uint8_t cbuf[4];
215 kfb.pixel2visual(cbuf, color);
216
217 for (sysarg_t y = y1; y < y2; y++) {
218 uint8_t *dst = kfb.addr + FB_POS(x1, y);
219
220 for (sysarg_t x = x1; x < x2; x++) {
221 memcpy(dst, cbuf, kfb.pixel_bytes);
222 dst += kfb.pixel_bytes;
223 }
224 }
225}
226
227static void vp_put_pixel(fbvp_t *vp, sysarg_t x, sysarg_t y, pixel_t pixel)
228{
229 put_pixel(vp->x + x, vp->y + y, pixel);
230}
231
232static void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
233{
234 switch (attrs.type) {
235 case CHAR_ATTR_STYLE:
236 switch (attrs.val.style) {
237 case STYLE_NORMAL:
238 *bgcolor = color_table[COLOR_WHITE];
239 *fgcolor = color_table[COLOR_BLACK];
240 break;
241 case STYLE_EMPHASIS:
242 *bgcolor = color_table[COLOR_WHITE];
243 *fgcolor = color_table[COLOR_RED];
244 break;
245 case STYLE_INVERTED:
246 *bgcolor = color_table[COLOR_BLACK];
247 *fgcolor = color_table[COLOR_WHITE];
248 break;
249 case STYLE_SELECTED:
250 *bgcolor = color_table[COLOR_RED];
251 *fgcolor = color_table[COLOR_WHITE];
252 break;
253 }
254 break;
255 case CHAR_ATTR_INDEX:
256 *bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
257 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
258 *fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
259 ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
260 break;
261 case CHAR_ATTR_RGB:
262 *bgcolor = attrs.val.rgb.bgcolor;
263 *fgcolor = attrs.val.rgb.fgcolor;
264 break;
265 }
266}
267
268/** Draw a character, takes advantage of alignment.
269 *
270 * This version can only be used if the following conditions are met:
271 *
272 * - word size is divisible by pixel_bytes
273 * - cell scanline size is divisible by word size
274 * - cell scanlines are word-aligned
275 *
276 * It makes use of the pre-rendered mask to process (possibly) several
277 * pixels at once (word size / pixel_bytes pixels at a time are processed)
278 * making it very fast. Most notably this version is not applicable at 24 bits
279 * per pixel.
280 *
281 * @param x X coordinate of top-left corner on screen.
282 * @param y Y coordinate of top-left corner on screen.
283 * @param inverted Draw inverted character.
284 * @param ch Character to draw.
285 * @param bgcolor Background color.
286 * @param fbgcolor Foreground color.
287 *
288 */
289static void draw_char_aligned(sysarg_t x, sysarg_t y, bool inverted, wchar_t ch,
290 pixel_t bgcolor, pixel_t fgcolor)
291{
292 size_t word_size = sizeof(unsigned long);
293
294 /*
295 * Prepare a pair of words, one filled with foreground-color
296 * pattern and the other filled with background-color pattern.
297 */
298 unsigned long fg_buf;
299 unsigned long bg_buf;
300
301 for (size_t i = 0; i < word_size / kfb.pixel_bytes; i++) {
302 kfb.pixel2visual(&((uint8_t *) &bg_buf)[i * kfb.pixel_bytes],
303 bgcolor);
304 kfb.pixel2visual(&((uint8_t *) &fg_buf)[i * kfb.pixel_bytes],
305 fgcolor);
306 }
307
308 /* Pointer to the current position in the mask. */
309 unsigned long *maskp =
310 (unsigned long *) &kfb.glyphs[GLYPH_POS(
311 fb_font_glyph(ch), 0, inverted)];
312
313 /* Pointer to the current position on the screen. */
314 unsigned long *dst =
315 (unsigned long *) &kfb.addr[FB_POS(x, y)];
316
317 /* Width of the character cell in words. */
318 size_t ww = FONT_WIDTH * kfb.pixel_bytes / word_size;
319
320 /* Offset to add when moving to another screen scanline. */
321 size_t d_add = kfb.scanline - FONT_WIDTH * kfb.pixel_bytes;
322
323 for (size_t yd = 0; yd < FONT_SCANLINES; yd++) {
324 /*
325 * Now process the cell scanline, combining foreground
326 * and background color patters using the pre-rendered mask.
327 */
328 for (size_t i = 0; i < ww; i++) {
329 unsigned long mask = *maskp++;
330 *dst++ = (fg_buf & mask) | (bg_buf & ~mask);
331 }
332
333 /* Move to the beginning of the next scanline of the cell. */
334 dst = (unsigned long *) ((uint8_t *) dst + d_add);
335 }
336}
337
338/** Draw a character, fallback version.
339 *
340 * This version does not make use of the pre-rendered mask, it uses
341 * the font bitmap directly. It works always, but it is slower.
342 *
343 * @param x X coordinate of top-left corner on screen.
344 * @param y Y coordinate of top-left corner on screen.
345 * @param inverted Draw inverted character.
346 * @param ch Character to draw.
347 * @param bgcolor Background color.
348 * @param fgcolor Foreground color.
349 *
350 */
351static void draw_char_fallback(sysarg_t x, sysarg_t y, bool inverted,
352 wchar_t ch, pixel_t bgcolor, pixel_t fgcolor)
353{
354 /* Character glyph */
355 uint16_t glyph = fb_font_glyph(ch);
356
357 /* Pre-render the foreground and background color pixels. */
358 uint8_t fg_buf[4];
359 uint8_t bg_buf[4];
360
361 if (inverted) {
362 kfb.pixel2visual(bg_buf, fgcolor);
363 kfb.pixel2visual(fg_buf, bgcolor);
364 } else {
365 kfb.pixel2visual(bg_buf, bgcolor);
366 kfb.pixel2visual(fg_buf, fgcolor);
367 }
368
369 /* Pointer to the current position on the screen. */
370 uint8_t *dst = (uint8_t *) &kfb.addr[FB_POS(x, y)];
371
372 /* Offset to add when moving to another screen scanline. */
373 size_t d_add = kfb.scanline - FONT_WIDTH * kfb.pixel_bytes;
374
375 for (size_t yd = 0; yd < FONT_SCANLINES; yd++) {
376 /* Byte containing bits of the glyph scanline. */
377 uint8_t byte = fb_font[glyph][yd];
378
379 for (size_t i = 0; i < FONT_WIDTH; i++) {
380 /* Choose color based on the current bit. */
381 uint8_t *src = (byte & 0x80) ? fg_buf : bg_buf;
382
383 /* Copy the pixel. */
384 for (size_t j = 0; j < kfb.pixel_bytes; j++)
385 *dst++ = *src++;
386
387 /* Move to the next bit. */
388 byte <<= 1;
389 }
390
391 /* Move to the beginning of the next scanline of the cell. */
392 dst += d_add;
393 }
394}
395
396/** Draw the character at the specified position in viewport.
397 *
398 * @param vp Viewport.
399 * @param col Screen position relative to viewport.
400 * @param row Screen position relative to viewport.
401 *
402 */
403static void draw_vp_char(fbvp_t *vp, sysarg_t col, sysarg_t row)
404{
405 kfb_vp_t *kfb_vp = (kfb_vp_t *) vp->data;
406
407 sysarg_t x = vp->x + COL2X(col);
408 sysarg_t y = vp->y + ROW2Y(row);
409
410 charfield_t *field = screenbuffer_field_at(vp->backbuf, col, row);
411
412 pixel_t bgcolor = 0;
413 pixel_t fgcolor = 0;
414 attrs_rgb(field->attrs, &bgcolor, &fgcolor);
415
416 bool inverted = (vp->cursor_flash) &&
417 screenbuffer_cursor_at(vp->backbuf, col, row);
418
419 (*kfb_vp->draw_char)(x, y, inverted, field->ch, bgcolor, fgcolor);
420}
421
422static errno_t kfb_yield(fbdev_t *dev)
423{
424 if (kfb.backbuf == NULL) {
425 kfb.backbuf =
426 malloc(kfb.width * kfb.height * kfb.pixel_bytes);
427 if (kfb.backbuf == NULL)
428 return ENOMEM;
429 }
430
431 for (sysarg_t y = 0; y < kfb.height; y++)
432 memcpy(kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
433 kfb.addr + FB_POS(0, y), kfb.width * kfb.pixel_bytes);
434
435 return EOK;
436}
437
438static errno_t kfb_claim(fbdev_t *dev)
439{
440 if (kfb.backbuf == NULL)
441 return ENOENT;
442
443 for (sysarg_t y = 0; y < kfb.height; y++)
444 memcpy(kfb.addr + FB_POS(0, y),
445 kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
446 kfb.width * kfb.pixel_bytes);
447
448 return EOK;
449}
450
451static void kfb_pointer_update(struct fbdev *dev, sysarg_t x, sysarg_t y,
452 bool visible)
453{
454 pointer_hide();
455
456 kfb.pointer_x = x;
457 kfb.pointer_y = y;
458 kfb.pointer_visible = visible;
459
460 pointer_show();
461}
462
463static errno_t kfb_get_resolution(fbdev_t *dev, sysarg_t *width, sysarg_t *height)
464{
465 *width = kfb.width;
466 *height = kfb.height;
467 return EOK;
468}
469
470static void kfb_font_metrics(fbdev_t *dev, sysarg_t width, sysarg_t height,
471 sysarg_t *cols, sysarg_t *rows)
472{
473 *cols = X2COL(width);
474 *rows = Y2ROW(height);
475}
476
477static errno_t kfb_vp_create(fbdev_t *dev, fbvp_t *vp)
478{
479 kfb_vp_t *kfb_vp = malloc(sizeof(kfb_vp_t));
480 if (kfb_vp == NULL)
481 return ENOMEM;
482
483 /*
484 * Conditions necessary to select aligned glyph
485 * drawing variants:
486 * - word size is divisible by number of bytes per pixel
487 * - cell scanline size is divisible by word size
488 * - cell scanlines are word-aligned
489 *
490 */
491 size_t word_size = sizeof(unsigned long);
492
493 if (((word_size % kfb.pixel_bytes) == 0) &&
494 ((FONT_WIDTH * kfb.pixel_bytes) % word_size == 0) &&
495 ((vp->x * kfb.pixel_bytes) % word_size == 0) &&
496 (kfb.scanline % word_size == 0))
497 kfb_vp->draw_char = draw_char_aligned;
498 else
499 kfb_vp->draw_char = draw_char_fallback;
500
501 vp->attrs.type = CHAR_ATTR_RGB;
502 vp->attrs.val.rgb.bgcolor = DEFAULT_BGCOLOR;
503 vp->attrs.val.rgb.fgcolor = DEFAULT_FGCOLOR;
504 vp->data = (void *) kfb_vp;
505
506 return EOK;
507}
508
509static void kfb_vp_destroy(fbdev_t *dev, fbvp_t *vp)
510{
511 free(vp->data);
512}
513
514static void kfb_vp_clear(fbdev_t *dev, fbvp_t *vp)
515{
516 pointer_hide();
517
518 for (sysarg_t row = 0; row < vp->rows; row++) {
519 for (sysarg_t col = 0; col < vp->cols; col++) {
520 charfield_t *field =
521 screenbuffer_field_at(vp->backbuf, col, row);
522
523 field->ch = 0;
524 field->attrs = vp->attrs;
525 }
526 }
527
528 pixel_t bgcolor = 0;
529 pixel_t fgcolor = 0;
530 attrs_rgb(vp->attrs, &bgcolor, &fgcolor);
531
532 draw_filled_rect(vp->x, vp->y, vp->x + vp->width,
533 vp->y + vp->height, bgcolor);
534
535 pointer_show();
536}
537
538static console_caps_t kfb_vp_get_caps(fbdev_t *dev, fbvp_t *vp)
539{
540 return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB);
541}
542
543static void kfb_vp_cursor_update(fbdev_t *dev, fbvp_t *vp, sysarg_t prev_col,
544 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
545{
546 pointer_hide();
547 draw_vp_char(vp, prev_col, prev_row);
548 draw_vp_char(vp, col, row);
549 pointer_show();
550}
551
552static void kfb_vp_cursor_flash(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
553 sysarg_t row)
554{
555 pointer_hide();
556 draw_vp_char(vp, col, row);
557 pointer_show();
558}
559
560static void kfb_vp_char_update(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
561 sysarg_t row)
562{
563 pointer_hide();
564 draw_vp_char(vp, col, row);
565 pointer_show();
566}
567
568static void kfb_vp_imgmap_damage(fbdev_t *dev, fbvp_t *vp, imgmap_t *imgmap,
569 sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height)
570{
571 pointer_hide();
572
573 for (sysarg_t y = 0; y < height; y++) {
574 for (sysarg_t x = 0; x < width; x++) {
575 pixel_t pixel = imgmap_get_pixel(imgmap, x0 + x, y0 + y);
576 vp_put_pixel(vp, x0 + x, y0 + y, pixel);
577 }
578 }
579
580 pointer_show();
581}
582
583static fbdev_ops_t kfb_ops = {
584 .yield = kfb_yield,
585 .claim = kfb_claim,
586 .pointer_update = kfb_pointer_update,
587 .get_resolution = kfb_get_resolution,
588 .font_metrics = kfb_font_metrics,
589 .vp_create = kfb_vp_create,
590 .vp_destroy = kfb_vp_destroy,
591 .vp_clear = kfb_vp_clear,
592 .vp_get_caps = kfb_vp_get_caps,
593 .vp_cursor_update = kfb_vp_cursor_update,
594 .vp_cursor_flash = kfb_vp_cursor_flash,
595 .vp_char_update = kfb_vp_char_update,
596 .vp_imgmap_damage = kfb_vp_imgmap_damage
597};
598
599/** Render glyphs
600 *
601 * Convert glyphs from device independent font
602 * description to current visual representation.
603 *
604 */
605static void render_glyphs(size_t sz)
606{
607 memset(kfb.glyphs, 0, sz);
608
609 for (unsigned int glyph = 0; glyph < FONT_GLYPHS; glyph++) {
610 for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
611 for (unsigned int x = 0; x < FONT_WIDTH; x++) {
612 kfb.visual_mask(
613 &kfb.glyphs[GLYPH_POS(glyph, y, false) + x * kfb.pixel_bytes],
614 (fb_font[glyph][y] & (1 << (7 - x))) ? true : false);
615 kfb.visual_mask(
616 &kfb.glyphs[GLYPH_POS(glyph, y, true) + x * kfb.pixel_bytes],
617 (fb_font[glyph][y] & (1 << (7 - x))) ? false : true);
618 }
619 }
620 }
621}
622
623errno_t kfb_init(void)
624{
625 sysarg_t present;
626 errno_t rc = sysinfo_get_value("fb", &present);
627 if (rc != EOK)
628 present = false;
629
630 if (!present)
631 return ENOENT;
632
633 sysarg_t kind;
634 rc = sysinfo_get_value("fb.kind", &kind);
635 if (rc != EOK)
636 kind = (sysarg_t) -1;
637
638 if (kind != 1)
639 return EINVAL;
640
641 sysarg_t paddr;
642 rc = sysinfo_get_value("fb.address.physical", &paddr);
643 if (rc != EOK)
644 return rc;
645
646 sysarg_t offset;
647 rc = sysinfo_get_value("fb.offset", &offset);
648 if (rc != EOK)
649 offset = 0;
650
651 sysarg_t width;
652 rc = sysinfo_get_value("fb.width", &width);
653 if (rc != EOK)
654 return rc;
655
656 sysarg_t height;
657 rc = sysinfo_get_value("fb.height", &height);
658 if (rc != EOK)
659 return rc;
660
661 sysarg_t scanline;
662 rc = sysinfo_get_value("fb.scanline", &scanline);
663 if (rc != EOK)
664 return rc;
665
666 sysarg_t visual;
667 rc = sysinfo_get_value("fb.visual", &visual);
668 if (rc != EOK)
669 return rc;
670
671 kfb.width = width;
672 kfb.height = height;
673 kfb.offset = offset;
674 kfb.scanline = scanline;
675 kfb.visual = visual;
676
677 switch (visual) {
678 case VISUAL_INDIRECT_8:
679 kfb.pixel2visual = pixel2bgr_323;
680 kfb.visual2pixel = bgr_323_2pixel;
681 kfb.visual_mask = visual_mask_323;
682 kfb.pixel_bytes = 1;
683 break;
684 case VISUAL_RGB_5_5_5_LE:
685 kfb.pixel2visual = pixel2rgb_555_le;
686 kfb.visual2pixel = rgb_555_le_2pixel;
687 kfb.visual_mask = visual_mask_555;
688 kfb.pixel_bytes = 2;
689 break;
690 case VISUAL_RGB_5_5_5_BE:
691 kfb.pixel2visual = pixel2rgb_555_be;
692 kfb.visual2pixel = rgb_555_be_2pixel;
693 kfb.visual_mask = visual_mask_555;
694 kfb.pixel_bytes = 2;
695 break;
696 case VISUAL_RGB_5_6_5_LE:
697 kfb.pixel2visual = pixel2rgb_565_le;
698 kfb.visual2pixel = rgb_565_le_2pixel;
699 kfb.visual_mask = visual_mask_565;
700 kfb.pixel_bytes = 2;
701 break;
702 case VISUAL_RGB_5_6_5_BE:
703 kfb.pixel2visual = pixel2rgb_565_be;
704 kfb.visual2pixel = rgb_565_be_2pixel;
705 kfb.visual_mask = visual_mask_565;
706 kfb.pixel_bytes = 2;
707 break;
708 case VISUAL_RGB_8_8_8:
709 kfb.pixel2visual = pixel2rgb_888;
710 kfb.visual2pixel = rgb_888_2pixel;
711 kfb.visual_mask = visual_mask_888;
712 kfb.pixel_bytes = 3;
713 break;
714 case VISUAL_BGR_8_8_8:
715 kfb.pixel2visual = pixel2bgr_888;
716 kfb.visual2pixel = bgr_888_2pixel;
717 kfb.visual_mask = visual_mask_888;
718 kfb.pixel_bytes = 3;
719 break;
720 case VISUAL_RGB_8_8_8_0:
721 kfb.pixel2visual = pixel2rgb_8880;
722 kfb.visual2pixel = rgb_8880_2pixel;
723 kfb.visual_mask = visual_mask_8880;
724 kfb.pixel_bytes = 4;
725 break;
726 case VISUAL_RGB_0_8_8_8:
727 kfb.pixel2visual = pixel2rgb_0888;
728 kfb.visual2pixel = rgb_0888_2pixel;
729 kfb.visual_mask = visual_mask_0888;
730 kfb.pixel_bytes = 4;
731 break;
732 case VISUAL_BGR_0_8_8_8:
733 kfb.pixel2visual = pixel2bgr_0888;
734 kfb.visual2pixel = bgr_0888_2pixel;
735 kfb.visual_mask = visual_mask_0888;
736 kfb.pixel_bytes = 4;
737 break;
738 case VISUAL_BGR_8_8_8_0:
739 kfb.pixel2visual = pixel2bgr_8880;
740 kfb.visual2pixel = bgr_8880_2pixel;
741 kfb.visual_mask = visual_mask_8880;
742 kfb.pixel_bytes = 4;
743 break;
744 default:
745 return EINVAL;
746 }
747
748 kfb.glyph_scanline = FONT_WIDTH * kfb.pixel_bytes;
749 kfb.glyph_bytes = kfb.glyph_scanline * FONT_SCANLINES;
750
751 size_t sz = 2 * FONT_GLYPHS * kfb.glyph_bytes;
752 kfb.glyphs = (uint8_t *) malloc(sz);
753 if (kfb.glyphs == NULL)
754 return EINVAL;
755
756 render_glyphs(sz);
757
758 kfb.size = scanline * height;
759
760 rc = physmem_map((void *) paddr + offset,
761 ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
762 AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
763 if (rc != EOK) {
764 free(kfb.glyphs);
765 return rc;
766 }
767
768 kfb.pointer_x = 0;
769 kfb.pointer_y = 0;
770 kfb.pointer_visible = false;
771 kfb.pointer_imgmap = imgmap_create(POINTER_WIDTH, POINTER_HEIGHT,
772 VISUAL_RGB_0_8_8_8, IMGMAP_FLAG_NONE);
773
774 kfb.backbuf = NULL;
775
776 fbdev_t *dev = fbdev_register(&kfb_ops, (void *) &kfb);
777 if (dev == NULL) {
778 free(kfb.glyphs);
779 as_area_destroy(kfb.addr);
780 return EINVAL;
781 }
782
783 return EOK;
784}
785
786/**
787 * @}
788 */
Note: See TracBrowser for help on using the repository browser.