00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00041 #include <stdlib.h>
00042 #include <unistd.h>
00043 #include <str.h>
00044 #include <ddi.h>
00045 #include <sysinfo.h>
00046 #include <align.h>
00047 #include <as.h>
00048 #include <ipc/fb.h>
00049 #include <ipc/ns.h>
00050 #include <ipc/services.h>
00051 #include <kernel/errno.h>
00052 #include <kernel/genarch/fb/visuals.h>
00053 #include <io/color.h>
00054 #include <io/style.h>
00055 #include <async.h>
00056 #include <fibril.h>
00057 #include <bool.h>
00058 #include <stdio.h>
00059 #include <byteorder.h>
00060 #include <io/screenbuffer.h>
00061
00062 #include "font-8x16.h"
00063 #include "fb.h"
00064 #include "main.h"
00065 #include "ppm.h"
00066
00067 #include "pointer.xbm"
00068 #include "pointer_mask.xbm"
00069
00070 #define DEFAULT_BGCOLOR 0xf0f0f0
00071 #define DEFAULT_FGCOLOR 0x000000
00072
00073 #define GLYPH_UNAVAIL '?'
00074
00075 #define MAX_ANIM_LEN 8
00076 #define MAX_ANIMATIONS 4
00077 #define MAX_PIXMAPS 256
00078 #define MAX_VIEWPORTS 128
00081 typedef void (*rgb_conv_t)(void *, uint32_t);
00082
00084 typedef void (*mask_conv_t)(void *, bool);
00085
00087 typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor,
00088 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
00089
00090 struct {
00091 uint8_t *fb_addr;
00092
00093 unsigned int xres;
00094 unsigned int yres;
00095
00096 unsigned int scanline;
00097 unsigned int glyphscanline;
00098
00099 unsigned int pixelbytes;
00100 unsigned int glyphbytes;
00101
00103 uint8_t *glyphs;
00104
00105 rgb_conv_t rgb_conv;
00106 mask_conv_t mask_conv;
00107 } screen;
00108
00110 typedef struct {
00111 uint32_t glyph;
00112 uint32_t fg_color;
00113 uint32_t bg_color;
00114 } bb_cell_t;
00115
00116 typedef struct {
00117 bool initialized;
00118 unsigned int x;
00119 unsigned int y;
00120 unsigned int width;
00121 unsigned int height;
00122
00123
00124 unsigned int cols;
00125 unsigned int rows;
00126
00127
00128
00129
00130
00132 attr_rgb_t attr;
00133
00134 uint8_t *bgpixel;
00135
00141 dg_t dglyph;
00142
00143
00144 bool cursor_active;
00145 unsigned int cur_col;
00146 unsigned int cur_row;
00147 bool cursor_shown;
00148
00149
00150 bb_cell_t *backbuf;
00151 unsigned int bbsize;
00152 } viewport_t;
00153
00154 typedef struct {
00155 bool initialized;
00156 bool enabled;
00157 unsigned int vp;
00158
00159 unsigned int pos;
00160 unsigned int animlen;
00161 unsigned int pixmaps[MAX_ANIM_LEN];
00162 } animation_t;
00163
00164 static animation_t animations[MAX_ANIMATIONS];
00165 static bool anims_enabled;
00166
00167 typedef struct {
00168 unsigned int width;
00169 unsigned int height;
00170 uint8_t *data;
00171 } pixmap_t;
00172
00173 static pixmap_t pixmaps[MAX_PIXMAPS];
00174 static viewport_t viewports[128];
00175
00176 static bool client_connected = false;
00178 static uint32_t color_table[16] = {
00179 [COLOR_BLACK] = 0x000000,
00180 [COLOR_BLUE] = 0x0000f0,
00181 [COLOR_GREEN] = 0x00f000,
00182 [COLOR_CYAN] = 0x00f0f0,
00183 [COLOR_RED] = 0xf00000,
00184 [COLOR_MAGENTA] = 0xf000f0,
00185 [COLOR_YELLOW] = 0xf0f000,
00186 [COLOR_WHITE] = 0xf0f0f0,
00187
00188 [8 + COLOR_BLACK] = 0x000000,
00189 [8 + COLOR_BLUE] = 0x0000ff,
00190 [8 + COLOR_GREEN] = 0x00ff00,
00191 [8 + COLOR_CYAN] = 0x00ffff,
00192 [8 + COLOR_RED] = 0xff0000,
00193 [8 + COLOR_MAGENTA] = 0xff00ff,
00194 [8 + COLOR_YELLOW] = 0xffff00,
00195 [8 + COLOR_WHITE] = 0xffffff,
00196 };
00197
00198 static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a);
00199 static int rgb_from_style(attr_rgb_t *rgb, int style);
00200 static int rgb_from_idx(attr_rgb_t *rgb, sysarg_t fg_color,
00201 sysarg_t bg_color, sysarg_t flags);
00202
00203 static int fb_set_color(viewport_t *vport, sysarg_t fg_color,
00204 sysarg_t bg_color, sysarg_t attr);
00205
00206 static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
00207 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
00208 static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,
00209 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
00210
00211 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
00212 unsigned int row);
00213
00214
00215 #define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
00216 #define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
00217 #define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
00218
00219 #define COL2X(col) ((col) * FONT_WIDTH)
00220 #define ROW2Y(row) ((row) * FONT_SCANLINES)
00221
00222 #define X2COL(x) ((x) / FONT_WIDTH)
00223 #define Y2ROW(y) ((y) / FONT_SCANLINES)
00224
00225 #define FB_POS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes)
00226 #define BB_POS(vport, col, row) ((row) * vport->cols + (col))
00227 #define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline)
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 static void rgb_0888(void *dst, uint32_t rgb)
00239 {
00240 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
00241 (RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
00242 }
00243
00244 static void bgr_0888(void *dst, uint32_t rgb)
00245 {
00246 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
00247 (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
00248 }
00249
00250 static void mask_0888(void *dst, bool mask)
00251 {
00252 bgr_0888(dst, mask ? 0xffffff : 0);
00253 }
00254
00255 static void rgb_8880(void *dst, uint32_t rgb)
00256 {
00257 *((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
00258 (GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
00259 }
00260
00261 static void bgr_8880(void *dst, uint32_t rgb)
00262 {
00263 *((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
00264 (GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
00265 }
00266
00267 static void mask_8880(void *dst, bool mask)
00268 {
00269 bgr_8880(dst, mask ? 0xffffff : 0);
00270 }
00271
00272 static void rgb_888(void *dst, uint32_t rgb)
00273 {
00274 ((uint8_t *) dst)[0] = RED(rgb, 8);
00275 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
00276 ((uint8_t *) dst)[2] = BLUE(rgb, 8);
00277 }
00278
00279 static void bgr_888(void *dst, uint32_t rgb)
00280 {
00281 ((uint8_t *) dst)[0] = BLUE(rgb, 8);
00282 ((uint8_t *) dst)[1] = GREEN(rgb, 8);
00283 ((uint8_t *) dst)[2] = RED(rgb, 8);
00284 }
00285
00286 static void mask_888(void *dst, bool mask)
00287 {
00288 bgr_888(dst, mask ? 0xffffff : 0);
00289 }
00290
00291 static void rgb_555_be(void *dst, uint32_t rgb)
00292 {
00293 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
00294 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
00295 }
00296
00297 static void rgb_555_le(void *dst, uint32_t rgb)
00298 {
00299 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
00300 GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
00301 }
00302
00303 static void rgb_565_be(void *dst, uint32_t rgb)
00304 {
00305 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
00306 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
00307 }
00308
00309 static void rgb_565_le(void *dst, uint32_t rgb)
00310 {
00311 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
00312 GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
00313 }
00314
00315 static void mask_555(void *dst, bool mask)
00316 {
00317 rgb_555_be(dst, mask ? 0xffffff : 0);
00318 }
00319
00320 static void mask_565(void *dst, bool mask)
00321 {
00322 rgb_565_be(dst, mask ? 0xffffff : 0);
00323 }
00324
00325 static void bgr_323(void *dst, uint32_t rgb)
00326 {
00327 *((uint8_t *) dst)
00328 = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
00329 }
00330
00331 static void mask_323(void *dst, bool mask)
00332 {
00333 bgr_323(dst, mask ? 0x0 : ~0x0);
00334 }
00335
00341 static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1,
00342 unsigned int y1, uint32_t color)
00343 {
00344 unsigned int x;
00345 unsigned int y;
00346 unsigned int copy_bytes;
00347
00348 uint8_t *sp;
00349 uint8_t *dp;
00350 uint8_t cbuf[4];
00351
00352 if ((y0 >= y1) || (x0 >= x1))
00353 return;
00354
00355 screen.rgb_conv(cbuf, color);
00356
00357 sp = &screen.fb_addr[FB_POS(x0, y0)];
00358 dp = sp;
00359
00360
00361 for (x = x0; x < x1; x++) {
00362 memcpy(dp, cbuf, screen.pixelbytes);
00363 dp += screen.pixelbytes;
00364 }
00365
00366 dp = sp + screen.scanline;
00367 copy_bytes = (x1 - x0) * screen.pixelbytes;
00368
00369
00370 for (y = y0 + 1; y < y1; y++) {
00371 memcpy(dp, sp, copy_bytes);
00372 dp += screen.scanline;
00373 }
00374 }
00375
00381 static void vport_redraw(viewport_t *vport)
00382 {
00383 unsigned int col;
00384 unsigned int row;
00385
00386 for (row = 0; row < vport->rows; row++) {
00387 for (col = 0; col < vport->cols; col++) {
00388 draw_vp_glyph(vport, false, col, row);
00389 }
00390 }
00391
00392 if (COL2X(vport->cols) < vport->width) {
00393 draw_filled_rect(
00394 vport->x + COL2X(vport->cols), vport->y,
00395 vport->x + vport->width, vport->y + vport->height,
00396 vport->attr.bg_color);
00397 }
00398
00399 if (ROW2Y(vport->rows) < vport->height) {
00400 draw_filled_rect(
00401 vport->x, vport->y + ROW2Y(vport->rows),
00402 vport->x + vport->width, vport->y + vport->height,
00403 vport->attr.bg_color);
00404 }
00405 }
00406
00407 static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color,
00408 uint32_t bg_color)
00409 {
00410 size_t i;
00411
00412 for (i = 0; i < len; i++) {
00413 backbuf[i].glyph = 0;
00414 backbuf[i].fg_color = fg_color;
00415 backbuf[i].bg_color = bg_color;
00416 }
00417 }
00418
00424 static void vport_clear(viewport_t *vport)
00425 {
00426 backbuf_clear(vport->backbuf, vport->cols * vport->rows,
00427 vport->attr.fg_color, vport->attr.bg_color);
00428 vport_redraw(vport);
00429 }
00430
00437 static void vport_scroll(viewport_t *vport, int lines)
00438 {
00439 unsigned int col;
00440 unsigned int row;
00441 unsigned int x;
00442 unsigned int y;
00443 uint32_t glyph;
00444 uint32_t fg_color;
00445 uint32_t bg_color;
00446 bb_cell_t *bbp;
00447 bb_cell_t *xbp;
00448
00449
00450
00451
00452
00453 y = vport->y;
00454 for (row = 0; row < vport->rows; row++) {
00455 x = vport->x;
00456 for (col = 0; col < vport->cols; col++) {
00457 if (((int) row + lines >= 0) &&
00458 ((int) row + lines < (int) vport->rows)) {
00459 xbp = &vport->backbuf[BB_POS(vport, col, row + lines)];
00460 bbp = &vport->backbuf[BB_POS(vport, col, row)];
00461
00462 glyph = xbp->glyph;
00463 fg_color = xbp->fg_color;
00464 bg_color = xbp->bg_color;
00465
00466 if ((bbp->glyph == glyph)
00467 && (bbp->fg_color == xbp->fg_color)
00468 && (bbp->bg_color == xbp->bg_color)) {
00469 x += FONT_WIDTH;
00470 continue;
00471 }
00472 } else {
00473 glyph = 0;
00474 fg_color = vport->attr.fg_color;
00475 bg_color = vport->attr.bg_color;
00476 }
00477
00478 (*vport->dglyph)(x, y, false, screen.glyphs, glyph,
00479 fg_color, bg_color);
00480 x += FONT_WIDTH;
00481 }
00482 y += FONT_SCANLINES;
00483 }
00484
00485
00486
00487
00488
00489 if (lines > 0) {
00490 memmove(vport->backbuf, vport->backbuf + vport->cols * lines,
00491 vport->cols * (vport->rows - lines) * sizeof(bb_cell_t));
00492 backbuf_clear(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)],
00493 vport->cols * lines, vport->attr.fg_color, vport->attr.bg_color);
00494 } else {
00495 memmove(vport->backbuf - vport->cols * lines, vport->backbuf,
00496 vport->cols * (vport->rows + lines) * sizeof(bb_cell_t));
00497 backbuf_clear(vport->backbuf, - vport->cols * lines,
00498 vport->attr.fg_color, vport->attr.bg_color);
00499 }
00500 }
00501
00508 static void render_glyphs(void)
00509 {
00510 unsigned int glyph;
00511
00512 for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
00513 unsigned int y;
00514
00515 for (y = 0; y < FONT_SCANLINES; y++) {
00516 unsigned int x;
00517
00518 for (x = 0; x < FONT_WIDTH; x++) {
00519 screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes],
00520 (fb_font[glyph][y] & (1 << (7 - x))) ? true : false);
00521
00522 screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes],
00523 (fb_font[glyph][y] & (1 << (7 - x))) ? false : true);
00524 }
00525 }
00526 }
00527 }
00528
00539 static int vport_create(unsigned int x, unsigned int y,
00540 unsigned int width, unsigned int height)
00541 {
00542 unsigned int i;
00543
00544 for (i = 0; i < MAX_VIEWPORTS; i++) {
00545 if (!viewports[i].initialized)
00546 break;
00547 }
00548
00549 if (i == MAX_VIEWPORTS)
00550 return ELIMIT;
00551
00552 unsigned int cols = width / FONT_WIDTH;
00553 unsigned int rows = height / FONT_SCANLINES;
00554 unsigned int bbsize = cols * rows * sizeof(bb_cell_t);
00555 unsigned int word_size = sizeof(unsigned long);
00556
00557 bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize);
00558 if (!backbuf)
00559 return ENOMEM;
00560
00561 uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes);
00562 if (!bgpixel) {
00563 free(backbuf);
00564 return ENOMEM;
00565 }
00566
00567 backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR);
00568 memset(bgpixel, 0, screen.pixelbytes);
00569
00570 viewports[i].x = x;
00571 viewports[i].y = y;
00572 viewports[i].width = width;
00573 viewports[i].height = height;
00574
00575 viewports[i].cols = cols;
00576 viewports[i].rows = rows;
00577
00578 viewports[i].attr.bg_color = DEFAULT_BGCOLOR;
00579 viewports[i].attr.fg_color = DEFAULT_FGCOLOR;
00580
00581 viewports[i].bgpixel = bgpixel;
00582
00583
00584
00585
00586
00587
00588
00589
00590 if (((word_size % screen.pixelbytes) == 0)
00591 && ((FONT_WIDTH * screen.pixelbytes) % word_size == 0)
00592 && ((x * screen.pixelbytes) % word_size == 0)
00593 && (screen.scanline % word_size == 0)) {
00594 viewports[i].dglyph = draw_glyph_aligned;
00595 } else {
00596 viewports[i].dglyph = draw_glyph_fallback;
00597 }
00598
00599 viewports[i].cur_col = 0;
00600 viewports[i].cur_row = 0;
00601 viewports[i].cursor_active = false;
00602 viewports[i].cursor_shown = false;
00603
00604 viewports[i].bbsize = bbsize;
00605 viewports[i].backbuf = backbuf;
00606
00607 viewports[i].initialized = true;
00608
00609 screen.rgb_conv(viewports[i].bgpixel, viewports[i].attr.bg_color);
00610
00611 return i;
00612 }
00613
00614
00624 static bool screen_init(void *addr, unsigned int xres, unsigned int yres,
00625 unsigned int scan, unsigned int visual)
00626 {
00627 switch (visual) {
00628 case VISUAL_INDIRECT_8:
00629 screen.rgb_conv = bgr_323;
00630 screen.mask_conv = mask_323;
00631 screen.pixelbytes = 1;
00632 break;
00633 case VISUAL_RGB_5_5_5_LE:
00634 screen.rgb_conv = rgb_555_le;
00635 screen.mask_conv = mask_555;
00636 screen.pixelbytes = 2;
00637 break;
00638 case VISUAL_RGB_5_5_5_BE:
00639 screen.rgb_conv = rgb_555_be;
00640 screen.mask_conv = mask_555;
00641 screen.pixelbytes = 2;
00642 break;
00643 case VISUAL_RGB_5_6_5_LE:
00644 screen.rgb_conv = rgb_565_le;
00645 screen.mask_conv = mask_565;
00646 screen.pixelbytes = 2;
00647 break;
00648 case VISUAL_RGB_5_6_5_BE:
00649 screen.rgb_conv = rgb_565_be;
00650 screen.mask_conv = mask_565;
00651 screen.pixelbytes = 2;
00652 break;
00653 case VISUAL_RGB_8_8_8:
00654 screen.rgb_conv = rgb_888;
00655 screen.mask_conv = mask_888;
00656 screen.pixelbytes = 3;
00657 break;
00658 case VISUAL_BGR_8_8_8:
00659 screen.rgb_conv = bgr_888;
00660 screen.mask_conv = mask_888;
00661 screen.pixelbytes = 3;
00662 break;
00663 case VISUAL_RGB_8_8_8_0:
00664 screen.rgb_conv = rgb_8880;
00665 screen.mask_conv = mask_8880;
00666 screen.pixelbytes = 4;
00667 break;
00668 case VISUAL_RGB_0_8_8_8:
00669 screen.rgb_conv = rgb_0888;
00670 screen.mask_conv = mask_0888;
00671 screen.pixelbytes = 4;
00672 break;
00673 case VISUAL_BGR_0_8_8_8:
00674 screen.rgb_conv = bgr_0888;
00675 screen.mask_conv = mask_0888;
00676 screen.pixelbytes = 4;
00677 break;
00678 case VISUAL_BGR_8_8_8_0:
00679 screen.rgb_conv = bgr_8880;
00680 screen.mask_conv = mask_8880;
00681 screen.pixelbytes = 4;
00682 break;
00683 default:
00684 return false;
00685 }
00686
00687 screen.fb_addr = (unsigned char *) addr;
00688 screen.xres = xres;
00689 screen.yres = yres;
00690 screen.scanline = scan;
00691
00692 screen.glyphscanline = FONT_WIDTH * screen.pixelbytes;
00693 screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES;
00694
00695 size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes;
00696 uint8_t *glyphs = (uint8_t *) malloc(glyphsize);
00697 if (!glyphs)
00698 return false;
00699
00700 memset(glyphs, 0, glyphsize);
00701 screen.glyphs = glyphs;
00702
00703 render_glyphs();
00704
00705
00706 vport_create(0, 0, xres, yres);
00707
00708 return true;
00709 }
00710
00711
00734 static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
00735 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color)
00736 {
00737 unsigned int i;
00738 unsigned int yd;
00739 unsigned long fg_buf;
00740 unsigned long bg_buf;
00741 unsigned long mask;
00742
00743
00744
00745
00746
00747 for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) {
00748 screen.rgb_conv(&((uint8_t *) &fg_buf)[i * screen.pixelbytes],
00749 fg_color);
00750 screen.rgb_conv(&((uint8_t *) &bg_buf)[i * screen.pixelbytes],
00751 bg_color);
00752 }
00753
00754
00755 unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)];
00756
00757
00758 unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)];
00759
00760
00761 unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long);
00762
00763
00764 unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;
00765
00766 for (yd = 0; yd < FONT_SCANLINES; yd++) {
00767
00768
00769
00770
00771 for (i = 0; i < ww; i++) {
00772 mask = *maskp++;
00773 *dp++ = (fg_buf & mask) | (bg_buf & ~mask);
00774 }
00775
00776
00777 dp = (unsigned long *) ((uint8_t *) dp + d_add);
00778 }
00779 }
00780
00795 void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,
00796 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color)
00797 {
00798 unsigned int i;
00799 unsigned int j;
00800 unsigned int yd;
00801 uint8_t fg_buf[4];
00802 uint8_t bg_buf[4];
00803 uint8_t *sp;
00804 uint8_t b;
00805
00806
00807 if (cursor) {
00808 screen.rgb_conv(fg_buf, bg_color);
00809 screen.rgb_conv(bg_buf, fg_color);
00810 } else {
00811 screen.rgb_conv(fg_buf, fg_color);
00812 screen.rgb_conv(bg_buf, bg_color);
00813 }
00814
00815
00816 uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)];
00817
00818
00819 unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;
00820
00821 for (yd = 0; yd < FONT_SCANLINES; yd++) {
00822
00823 b = fb_font[glyph][yd];
00824
00825 for (i = 0; i < FONT_WIDTH; i++) {
00826
00827 sp = (b & 0x80) ? fg_buf : bg_buf;
00828
00829
00830 for (j = 0; j < screen.pixelbytes; j++) {
00831 *dp++ = *sp++;
00832 }
00833
00834
00835 b = b << 1;
00836 }
00837
00838
00839 dp += d_add;
00840 }
00841 }
00842
00851 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
00852 unsigned int row)
00853 {
00854 unsigned int x = vport->x + COL2X(col);
00855 unsigned int y = vport->y + ROW2Y(row);
00856
00857 uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph;
00858 uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color;
00859 uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color;
00860
00861 (*vport->dglyph)(x, y, cursor, screen.glyphs, glyph,
00862 fg_color, bg_color);
00863 }
00864
00868 static void cursor_hide(viewport_t *vport)
00869 {
00870 if ((vport->cursor_active) && (vport->cursor_shown)) {
00871 draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row);
00872 vport->cursor_shown = false;
00873 }
00874 }
00875
00876
00880 static void cursor_show(viewport_t *vport)
00881 {
00882
00883 if (vport->cursor_active) {
00884 draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row);
00885 vport->cursor_shown = true;
00886 }
00887 }
00888
00889
00893 static void cursor_blink(viewport_t *vport)
00894 {
00895 if (vport->cursor_shown)
00896 cursor_hide(vport);
00897 else
00898 cursor_show(vport);
00899 }
00900
00901
00910 static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row)
00911 {
00912 bb_cell_t *bbp;
00913
00914
00915 if ((vport->cursor_active) && (vport->cursor_shown) &&
00916 ((vport->cur_col != col) || (vport->cur_row != row)))
00917 cursor_hide(vport);
00918
00919 bbp = &vport->backbuf[BB_POS(vport, col, row)];
00920 bbp->glyph = fb_font_glyph(c);
00921 bbp->fg_color = vport->attr.fg_color;
00922 bbp->bg_color = vport->attr.bg_color;
00923
00924 draw_vp_glyph(vport, false, col, row);
00925
00926 vport->cur_col = col;
00927 vport->cur_row = row;
00928
00929 vport->cur_col++;
00930 if (vport->cur_col >= vport->cols) {
00931 vport->cur_col = 0;
00932 vport->cur_row++;
00933 if (vport->cur_row >= vport->rows)
00934 vport->cur_row--;
00935 }
00936
00937 cursor_show(vport);
00938 }
00939
00950 static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x,
00951 unsigned int y, unsigned int w, unsigned int h)
00952 {
00953 unsigned int i;
00954 unsigned int j;
00955 bb_cell_t *bbp;
00956 attrs_t *a;
00957
00958 for (j = 0; j < h; j++) {
00959 for (i = 0; i < w; i++) {
00960 unsigned int col = x + i;
00961 unsigned int row = y + j;
00962
00963 bbp = &vport->backbuf[BB_POS(vport, col, row)];
00964
00965 a = &data[j * w + i].attrs;
00966
00967 attr_rgb_t rgb;
00968 rgb.fg_color = 0;
00969 rgb.bg_color = 0;
00970 rgb_from_attr(&rgb, a);
00971
00972 bbp->glyph = fb_font_glyph(data[j * w + i].character);
00973 bbp->fg_color = rgb.fg_color;
00974 bbp->bg_color = rgb.bg_color;
00975
00976 draw_vp_glyph(vport, false, col, row);
00977 }
00978 }
00979 cursor_show(vport);
00980 }
00981
00982
00983 static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
00984 {
00985 int pm = *((int *) data);
00986 pixmap_t *pmap = &pixmaps[pm];
00987 unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
00988
00989 screen.rgb_conv(&pmap->data[pos], color);
00990 }
00991
00992
00993 static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
00994 {
00995 viewport_t *vport = (viewport_t *) data;
00996 unsigned int dx = vport->x + x;
00997 unsigned int dy = vport->y + y;
00998
00999 screen.rgb_conv(&screen.fb_addr[FB_POS(dx, dy)], color);
01000 }
01001
01002
01006 static int find_free_pixmap(void)
01007 {
01008 unsigned int i;
01009
01010 for (i = 0; i < MAX_PIXMAPS; i++)
01011 if (!pixmaps[i].data)
01012 return i;
01013
01014 return -1;
01015 }
01016
01017
01021 static int shm2pixmap(unsigned char *shm, size_t size)
01022 {
01023 int pm;
01024 pixmap_t *pmap;
01025
01026 pm = find_free_pixmap();
01027 if (pm == -1)
01028 return ELIMIT;
01029
01030 pmap = &pixmaps[pm];
01031
01032 if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
01033 return EINVAL;
01034
01035 pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
01036 if (!pmap->data)
01037 return ENOMEM;
01038
01039 ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
01040
01041 return pm;
01042 }
01043
01044
01067 static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
01068 {
01069 static keyfield_t *interbuffer = NULL;
01070 static size_t intersize = 0;
01071
01072 static unsigned char *shm = NULL;
01073 static sysarg_t shm_id = 0;
01074 static size_t shm_size;
01075
01076 bool handled = true;
01077 int retval = EOK;
01078 viewport_t *vport = &viewports[vp];
01079 unsigned int x;
01080 unsigned int y;
01081 unsigned int w;
01082 unsigned int h;
01083
01084 switch (IPC_GET_IMETHOD(*call)) {
01085 case IPC_M_SHARE_OUT:
01086
01087 if (IPC_GET_ARG1(*call) == shm_id) {
01088 void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
01089 shm_size = IPC_GET_ARG2(*call);
01090 if (async_answer_1(callid, EOK, (sysarg_t) dest)) {
01091 shm_id = 0;
01092 return false;
01093 }
01094 shm = dest;
01095
01096 if (shm[0] != 'P')
01097 return false;
01098
01099 return true;
01100 } else {
01101 intersize = IPC_GET_ARG2(*call);
01102 receive_comm_area(callid, call, (void *) &interbuffer);
01103 }
01104 return true;
01105 case FB_PREPARE_SHM:
01106 if (shm_id)
01107 retval = EBUSY;
01108 else
01109 shm_id = IPC_GET_ARG1(*call);
01110 break;
01111
01112 case FB_DROP_SHM:
01113 if (shm) {
01114 as_area_destroy(shm);
01115 shm = NULL;
01116 }
01117 shm_id = 0;
01118 break;
01119
01120 case FB_SHM2PIXMAP:
01121 if (!shm) {
01122 retval = EINVAL;
01123 break;
01124 }
01125 retval = shm2pixmap(shm, shm_size);
01126 break;
01127 case FB_DRAW_PPM:
01128 if (!shm) {
01129 retval = EINVAL;
01130 break;
01131 }
01132 x = IPC_GET_ARG1(*call);
01133 y = IPC_GET_ARG2(*call);
01134
01135 if ((x > vport->width) || (y > vport->height)) {
01136 retval = EINVAL;
01137 break;
01138 }
01139
01140 ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
01141 IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
01142 break;
01143 case FB_DRAW_TEXT_DATA:
01144 x = IPC_GET_ARG1(*call);
01145 y = IPC_GET_ARG2(*call);
01146 w = IPC_GET_ARG3(*call);
01147 h = IPC_GET_ARG4(*call);
01148 if (!interbuffer) {
01149 retval = EINVAL;
01150 break;
01151 }
01152 if (x + w > vport->cols || y + h > vport->rows) {
01153 retval = EINVAL;
01154 break;
01155 }
01156 if (intersize < w * h * sizeof(*interbuffer)) {
01157 retval = EINVAL;
01158 break;
01159 }
01160 draw_text_data(vport, interbuffer, x, y, w, h);
01161 break;
01162 default:
01163 handled = false;
01164 }
01165
01166 if (handled)
01167 async_answer_0(callid, retval);
01168 return handled;
01169 }
01170
01171
01172 static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
01173 {
01174 unsigned int width = vport->width;
01175 unsigned int height = vport->height;
01176
01177 if (width + vport->x > screen.xres)
01178 width = screen.xres - vport->x;
01179 if (height + vport->y > screen.yres)
01180 height = screen.yres - vport->y;
01181
01182 unsigned int realwidth = pmap->width <= width ? pmap->width : width;
01183 unsigned int realheight = pmap->height <= height ? pmap->height : height;
01184
01185 unsigned int srcrowsize = vport->width * screen.pixelbytes;
01186 unsigned int realrowsize = realwidth * screen.pixelbytes;
01187
01188 unsigned int y;
01189 for (y = 0; y < realheight; y++) {
01190 unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
01191 memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
01192 }
01193 }
01194
01195
01199 static int save_vp_to_pixmap(viewport_t *vport)
01200 {
01201 int pm;
01202 pixmap_t *pmap;
01203
01204 pm = find_free_pixmap();
01205 if (pm == -1)
01206 return ELIMIT;
01207
01208 pmap = &pixmaps[pm];
01209 pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
01210 if (!pmap->data)
01211 return ENOMEM;
01212
01213 pmap->width = vport->width;
01214 pmap->height = vport->height;
01215
01216 copy_vp_to_pixmap(vport, pmap);
01217
01218 return pm;
01219 }
01220
01221
01228 static int draw_pixmap(int vp, int pm)
01229 {
01230 pixmap_t *pmap = &pixmaps[pm];
01231 viewport_t *vport = &viewports[vp];
01232
01233 unsigned int width = vport->width;
01234 unsigned int height = vport->height;
01235
01236 if (width + vport->x > screen.xres)
01237 width = screen.xres - vport->x;
01238 if (height + vport->y > screen.yres)
01239 height = screen.yres - vport->y;
01240
01241 if (!pmap->data)
01242 return EINVAL;
01243
01244 unsigned int realwidth = pmap->width <= width ? pmap->width : width;
01245 unsigned int realheight = pmap->height <= height ? pmap->height : height;
01246
01247 unsigned int srcrowsize = vport->width * screen.pixelbytes;
01248 unsigned int realrowsize = realwidth * screen.pixelbytes;
01249
01250 unsigned int y;
01251 for (y = 0; y < realheight; y++) {
01252 unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
01253 memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
01254 }
01255
01256 return EOK;
01257 }
01258
01259
01263 static void anims_tick(void)
01264 {
01265 unsigned int i;
01266 static int counts = 0;
01267
01268
01269 counts = (counts + 1) % 8;
01270 if (counts)
01271 return;
01272
01273 for (i = 0; i < MAX_ANIMATIONS; i++) {
01274 if ((!animations[i].animlen) || (!animations[i].initialized) ||
01275 (!animations[i].enabled))
01276 continue;
01277
01278 draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
01279 animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
01280 }
01281 }
01282
01283
01284 static unsigned int pointer_x;
01285 static unsigned int pointer_y;
01286 static bool pointer_shown, pointer_enabled;
01287 static int pointer_vport = -1;
01288 static int pointer_pixmap = -1;
01289
01290
01291 static void mouse_show(void)
01292 {
01293 int i, j;
01294 int visibility;
01295 int color;
01296 int bytepos;
01297
01298 if ((pointer_shown) || (!pointer_enabled))
01299 return;
01300
01301
01302 if (pointer_vport == -1) {
01303 pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height);
01304 if (pointer_vport < 0)
01305 return;
01306 } else {
01307 viewports[pointer_vport].x = pointer_x;
01308 viewports[pointer_vport].y = pointer_y;
01309 }
01310
01311 if (pointer_pixmap == -1)
01312 pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
01313 else
01314 copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
01315
01316
01317 for (i = 0; i < pointer_height; i++)
01318 for (j = 0; j < pointer_width; j++) {
01319 bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8;
01320 visibility = pointer_mask_bits[bytepos] &
01321 (1 << (j % 8));
01322 if (visibility) {
01323 color = pointer_bits[bytepos] &
01324 (1 << (j % 8)) ? 0 : 0xffffff;
01325 if (pointer_x + j < screen.xres && pointer_y +
01326 i < screen.yres)
01327 putpixel(&viewports[0], pointer_x + j,
01328 pointer_y + i, color);
01329 }
01330 }
01331 pointer_shown = 1;
01332 }
01333
01334
01335 static void mouse_hide(void)
01336 {
01337
01338 if (pointer_shown) {
01339 draw_pixmap(pointer_vport, pointer_pixmap);
01340 pointer_shown = 0;
01341 }
01342 }
01343
01344
01345 static void mouse_move(unsigned int x, unsigned int y)
01346 {
01347 mouse_hide();
01348 pointer_x = x % screen.xres;
01349 pointer_y = y % screen.yres;
01350 mouse_show();
01351 }
01352
01353
01354 static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
01355 {
01356 bool handled = true;
01357 int retval = EOK;
01358 int i, nvp;
01359 int newval;
01360
01361 switch (IPC_GET_IMETHOD(*call)) {
01362 case FB_ANIM_CREATE:
01363 nvp = IPC_GET_ARG1(*call);
01364 if (nvp == -1)
01365 nvp = vp;
01366 if (nvp >= MAX_VIEWPORTS || nvp < 0 ||
01367 !viewports[nvp].initialized) {
01368 retval = EINVAL;
01369 break;
01370 }
01371 for (i = 0; i < MAX_ANIMATIONS; i++) {
01372 if (!animations[i].initialized)
01373 break;
01374 }
01375 if (i == MAX_ANIMATIONS) {
01376 retval = ELIMIT;
01377 break;
01378 }
01379 animations[i].initialized = 1;
01380 animations[i].animlen = 0;
01381 animations[i].pos = 0;
01382 animations[i].enabled = 0;
01383 animations[i].vp = nvp;
01384 retval = i;
01385 break;
01386 case FB_ANIM_DROP:
01387 i = IPC_GET_ARG1(*call);
01388 if (i >= MAX_ANIMATIONS || i < 0) {
01389 retval = EINVAL;
01390 break;
01391 }
01392 animations[i].initialized = 0;
01393 break;
01394 case FB_ANIM_ADDPIXMAP:
01395 i = IPC_GET_ARG1(*call);
01396 if (i >= MAX_ANIMATIONS || i < 0 ||
01397 !animations[i].initialized) {
01398 retval = EINVAL;
01399 break;
01400 }
01401 if (animations[i].animlen == MAX_ANIM_LEN) {
01402 retval = ELIMIT;
01403 break;
01404 }
01405 newval = IPC_GET_ARG2(*call);
01406 if (newval < 0 || newval > MAX_PIXMAPS ||
01407 !pixmaps[newval].data) {
01408 retval = EINVAL;
01409 break;
01410 }
01411 animations[i].pixmaps[animations[i].animlen++] = newval;
01412 break;
01413 case FB_ANIM_CHGVP:
01414 i = IPC_GET_ARG1(*call);
01415 if (i >= MAX_ANIMATIONS || i < 0) {
01416 retval = EINVAL;
01417 break;
01418 }
01419 nvp = IPC_GET_ARG2(*call);
01420 if (nvp == -1)
01421 nvp = vp;
01422 if (nvp >= MAX_VIEWPORTS || nvp < 0 ||
01423 !viewports[nvp].initialized) {
01424 retval = EINVAL;
01425 break;
01426 }
01427 animations[i].vp = nvp;
01428 break;
01429 case FB_ANIM_START:
01430 case FB_ANIM_STOP:
01431 i = IPC_GET_ARG1(*call);
01432 if (i >= MAX_ANIMATIONS || i < 0) {
01433 retval = EINVAL;
01434 break;
01435 }
01436 newval = (IPC_GET_IMETHOD(*call) == FB_ANIM_START);
01437 if (newval ^ animations[i].enabled) {
01438 animations[i].enabled = newval;
01439 anims_enabled += newval ? 1 : -1;
01440 }
01441 break;
01442 default:
01443 handled = 0;
01444 }
01445 if (handled)
01446 async_answer_0(callid, retval);
01447 return handled;
01448 }
01449
01450
01454 static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
01455 {
01456 bool handled = true;
01457 int retval = EOK;
01458 int i, nvp;
01459
01460 switch (IPC_GET_IMETHOD(*call)) {
01461 case FB_VP_DRAW_PIXMAP:
01462 nvp = IPC_GET_ARG1(*call);
01463 if (nvp == -1)
01464 nvp = vp;
01465 if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
01466 !viewports[nvp].initialized) {
01467 retval = EINVAL;
01468 break;
01469 }
01470 i = IPC_GET_ARG2(*call);
01471 retval = draw_pixmap(nvp, i);
01472 break;
01473 case FB_VP2PIXMAP:
01474 nvp = IPC_GET_ARG1(*call);
01475 if (nvp == -1)
01476 nvp = vp;
01477 if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
01478 !viewports[nvp].initialized)
01479 retval = EINVAL;
01480 else
01481 retval = save_vp_to_pixmap(&viewports[nvp]);
01482 break;
01483 case FB_DROP_PIXMAP:
01484 i = IPC_GET_ARG1(*call);
01485 if (i >= MAX_PIXMAPS) {
01486 retval = EINVAL;
01487 break;
01488 }
01489 if (pixmaps[i].data) {
01490 free(pixmaps[i].data);
01491 pixmaps[i].data = NULL;
01492 }
01493 break;
01494 default:
01495 handled = 0;
01496 }
01497
01498 if (handled)
01499 async_answer_0(callid, retval);
01500 return handled;
01501
01502 }
01503
01504 static int rgb_from_style(attr_rgb_t *rgb, int style)
01505 {
01506 switch (style) {
01507 case STYLE_NORMAL:
01508 rgb->fg_color = color_table[COLOR_BLACK];
01509 rgb->bg_color = color_table[COLOR_WHITE];
01510 break;
01511 case STYLE_EMPHASIS:
01512 rgb->fg_color = color_table[COLOR_RED];
01513 rgb->bg_color = color_table[COLOR_WHITE];
01514 break;
01515 case STYLE_INVERTED:
01516 rgb->fg_color = color_table[COLOR_WHITE];
01517 rgb->bg_color = color_table[COLOR_BLACK];
01518 break;
01519 case STYLE_SELECTED:
01520 rgb->fg_color = color_table[COLOR_WHITE];
01521 rgb->bg_color = color_table[COLOR_RED];
01522 break;
01523 default:
01524 return EINVAL;
01525 }
01526
01527 return EOK;
01528 }
01529
01530 static int rgb_from_idx(attr_rgb_t *rgb, sysarg_t fg_color,
01531 sysarg_t bg_color, sysarg_t flags)
01532 {
01533 fg_color = (fg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);
01534 bg_color = (bg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);
01535
01536 rgb->fg_color = color_table[fg_color];
01537 rgb->bg_color = color_table[bg_color];
01538
01539 return EOK;
01540 }
01541
01542 static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a)
01543 {
01544 int rc;
01545
01546 switch (a->t) {
01547 case at_style:
01548 rc = rgb_from_style(rgb, a->a.s.style);
01549 break;
01550 case at_idx:
01551 rc = rgb_from_idx(rgb, a->a.i.fg_color,
01552 a->a.i.bg_color, a->a.i.flags);
01553 break;
01554 case at_rgb:
01555 *rgb = a->a.r;
01556 rc = EOK;
01557 break;
01558 }
01559
01560 return rc;
01561 }
01562
01563 static int fb_set_style(viewport_t *vport, sysarg_t style)
01564 {
01565 return rgb_from_style(&vport->attr, (int) style);
01566 }
01567
01568 static int fb_set_color(viewport_t *vport, sysarg_t fg_color,
01569 sysarg_t bg_color, sysarg_t flags)
01570 {
01571 return rgb_from_idx(&vport->attr, fg_color, bg_color, flags);
01572 }
01573
01577 static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
01578 {
01579 unsigned int vp = 0;
01580 viewport_t *vport = &viewports[vp];
01581
01582 if (client_connected) {
01583 async_answer_0(iid, ELIMIT);
01584 return;
01585 }
01586
01587
01588 client_connected = true;
01589 async_answer_0(iid, EOK);
01590
01591 while (true) {
01592 ipc_callid_t callid;
01593 ipc_call_t call;
01594 int retval;
01595 unsigned int i;
01596 int scroll;
01597 wchar_t ch;
01598 unsigned int col, row;
01599
01600 if ((vport->cursor_active) || (anims_enabled))
01601 callid = async_get_call_timeout(&call, 250000);
01602 else
01603 callid = async_get_call(&call);
01604
01605 mouse_hide();
01606 if (!callid) {
01607 cursor_blink(vport);
01608 anims_tick();
01609 mouse_show();
01610 continue;
01611 }
01612
01613 if (shm_handle(callid, &call, vp))
01614 continue;
01615
01616 if (pixmap_handle(callid, &call, vp))
01617 continue;
01618
01619 if (anim_handle(callid, &call, vp))
01620 continue;
01621
01622 switch (IPC_GET_IMETHOD(call)) {
01623 case IPC_M_PHONE_HUNGUP:
01624 client_connected = false;
01625
01626
01627 for (i = 1; i < MAX_VIEWPORTS; i++)
01628 vport->initialized = false;
01629
01630
01631 return;
01632
01633 case FB_PUTCHAR:
01634 ch = IPC_GET_ARG1(call);
01635 col = IPC_GET_ARG2(call);
01636 row = IPC_GET_ARG3(call);
01637
01638 if ((col >= vport->cols) || (row >= vport->rows)) {
01639 retval = EINVAL;
01640 break;
01641 }
01642 async_answer_0(callid, EOK);
01643
01644 draw_char(vport, ch, col, row);
01645
01646
01647 continue;
01648 case FB_CLEAR:
01649 vport_clear(vport);
01650 cursor_show(vport);
01651 retval = EOK;
01652 break;
01653 case FB_CURSOR_GOTO:
01654 col = IPC_GET_ARG1(call);
01655 row = IPC_GET_ARG2(call);
01656
01657 if ((col >= vport->cols) || (row >= vport->rows)) {
01658 retval = EINVAL;
01659 break;
01660 }
01661 retval = EOK;
01662
01663 cursor_hide(vport);
01664 vport->cur_col = col;
01665 vport->cur_row = row;
01666 cursor_show(vport);
01667 break;
01668 case FB_CURSOR_VISIBILITY:
01669 cursor_hide(vport);
01670 vport->cursor_active = IPC_GET_ARG1(call);
01671 cursor_show(vport);
01672 retval = EOK;
01673 break;
01674 case FB_GET_CSIZE:
01675 async_answer_2(callid, EOK, vport->cols, vport->rows);
01676 continue;
01677 case FB_GET_COLOR_CAP:
01678 async_answer_1(callid, EOK, FB_CCAP_RGB);
01679 continue;
01680 case FB_SCROLL:
01681 scroll = IPC_GET_ARG1(call);
01682 if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) {
01683 retval = EINVAL;
01684 break;
01685 }
01686 cursor_hide(vport);
01687 vport_scroll(vport, scroll);
01688 cursor_show(vport);
01689 retval = EOK;
01690 break;
01691 case FB_VIEWPORT_SWITCH:
01692 i = IPC_GET_ARG1(call);
01693 if (i >= MAX_VIEWPORTS) {
01694 retval = EINVAL;
01695 break;
01696 }
01697 if (!viewports[i].initialized) {
01698 retval = EADDRNOTAVAIL;
01699 break;
01700 }
01701 cursor_hide(vport);
01702 vp = i;
01703 vport = &viewports[vp];
01704 cursor_show(vport);
01705 retval = EOK;
01706 break;
01707 case FB_VIEWPORT_CREATE:
01708 retval = vport_create(IPC_GET_ARG1(call) >> 16,
01709 IPC_GET_ARG1(call) & 0xffff,
01710 IPC_GET_ARG2(call) >> 16,
01711 IPC_GET_ARG2(call) & 0xffff);
01712 break;
01713 case FB_VIEWPORT_DELETE:
01714 i = IPC_GET_ARG1(call);
01715 if (i >= MAX_VIEWPORTS) {
01716 retval = EINVAL;
01717 break;
01718 }
01719 if (!viewports[i].initialized) {
01720 retval = EADDRNOTAVAIL;
01721 break;
01722 }
01723 viewports[i].initialized = false;
01724 if (viewports[i].bgpixel)
01725 free(viewports[i].bgpixel);
01726 if (viewports[i].backbuf)
01727 free(viewports[i].backbuf);
01728 retval = EOK;
01729 break;
01730 case FB_SET_STYLE:
01731 retval = fb_set_style(vport, IPC_GET_ARG1(call));
01732 break;
01733 case FB_SET_COLOR:
01734 retval = fb_set_color(vport, IPC_GET_ARG1(call),
01735 IPC_GET_ARG2(call), IPC_GET_ARG3(call));
01736 break;
01737 case FB_SET_RGB_COLOR:
01738 vport->attr.fg_color = IPC_GET_ARG1(call);
01739 vport->attr.bg_color = IPC_GET_ARG2(call);
01740 retval = EOK;
01741 break;
01742 case FB_GET_RESOLUTION:
01743 async_answer_2(callid, EOK, screen.xres, screen.yres);
01744 continue;
01745 case FB_POINTER_MOVE:
01746 pointer_enabled = true;
01747 mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
01748 retval = EOK;
01749 break;
01750 case FB_SCREEN_YIELD:
01751 case FB_SCREEN_RECLAIM:
01752 retval = EOK;
01753 break;
01754 default:
01755 retval = ENOENT;
01756 }
01757 async_answer_0(callid, retval);
01758 }
01759 }
01760
01764 int fb_init(void)
01765 {
01766 async_set_client_connection(fb_client_connection);
01767
01768 sysarg_t fb_ph_addr;
01769 if (sysinfo_get_value("fb.address.physical", &fb_ph_addr) != EOK)
01770 return -1;
01771
01772 sysarg_t fb_offset;
01773 if (sysinfo_get_value("fb.offset", &fb_offset) != EOK)
01774 fb_offset = 0;
01775
01776 sysarg_t fb_width;
01777 if (sysinfo_get_value("fb.width", &fb_width) != EOK)
01778 return -1;
01779
01780 sysarg_t fb_height;
01781 if (sysinfo_get_value("fb.height", &fb_height) != EOK)
01782 return -1;
01783
01784 sysarg_t fb_scanline;
01785 if (sysinfo_get_value("fb.scanline", &fb_scanline) != EOK)
01786 return -1;
01787
01788 sysarg_t fb_visual;
01789 if (sysinfo_get_value("fb.visual", &fb_visual) != EOK)
01790 return -1;
01791
01792 sysarg_t fbsize = fb_scanline * fb_height;
01793 void *fb_addr = as_get_mappable_page(fbsize);
01794
01795 if (physmem_map((void *) fb_ph_addr + fb_offset, fb_addr,
01796 ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
01797 return -1;
01798
01799 if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual))
01800 return 0;
01801
01802 return -1;
01803 }
01804