Rev 3739 | Rev 3792 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3739 | Rev 3744 | ||
---|---|---|---|
Line 69... | Line 69... | ||
69 | #define MAX_ANIM_LEN 8 |
69 | #define MAX_ANIM_LEN 8 |
70 | #define MAX_ANIMATIONS 4 |
70 | #define MAX_ANIMATIONS 4 |
71 | #define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
71 | #define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ |
72 | #define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
72 | #define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ |
73 | 73 | ||
- | 74 | /** Function to render a pixel from a RGB value. */ |
|
74 | typedef void (*rgb_conv_t)(void *, uint32_t); |
75 | typedef void (*rgb_conv_t)(void *, uint32_t); |
75 | 76 | ||
- | 77 | /** Function to draw a glyph. */ |
|
- | 78 | typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, |
|
- | 79 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
- | 80 | ||
76 | struct { |
81 | struct { |
77 | uint8_t *fb_addr; |
82 | uint8_t *fb_addr; |
78 | 83 | ||
79 | unsigned int xres; |
84 | unsigned int xres; |
80 | unsigned int yres; |
85 | unsigned int yres; |
Line 97... | Line 102... | ||
97 | 102 | ||
98 | /* Text support in window */ |
103 | /* Text support in window */ |
99 | unsigned int cols; |
104 | unsigned int cols; |
100 | unsigned int rows; |
105 | unsigned int rows; |
101 | 106 | ||
- | 107 | /* |
|
102 | /* Style and glyphs for text printing */ |
108 | * Style and glyphs for text printing |
- | 109 | */ |
|
- | 110 | ||
- | 111 | /** Current style. */ |
|
103 | style_t style; |
112 | style_t style; |
- | 113 | ||
- | 114 | /** Pre-rendered mask for rendering glyphs. Different viewports |
|
- | 115 | * might use different drawing functions depending on whether their |
|
- | 116 | * scanlines are aligned on a word boundary.*/ |
|
104 | uint8_t *glyphs; |
117 | uint8_t *glyphs; |
- | 118 | ||
105 | uint8_t *bgpixel; |
119 | uint8_t *bgpixel; |
- | 120 | ||
- | 121 | /** Glyph drawing function for this viewport. */ |
|
- | 122 | dg_t dglyph; |
|
106 | 123 | ||
107 | /* Auto-cursor position */ |
124 | /* Auto-cursor position */ |
108 | bool cursor_active; |
125 | bool cursor_active; |
109 | unsigned int cur_col; |
126 | unsigned int cur_col; |
110 | unsigned int cur_row; |
127 | unsigned int cur_row; |
Line 137... | Line 154... | ||
137 | static pixmap_t pixmaps[MAX_PIXMAPS]; |
154 | static pixmap_t pixmaps[MAX_PIXMAPS]; |
138 | static viewport_t viewports[128]; |
155 | static viewport_t viewports[128]; |
139 | 156 | ||
140 | static bool client_connected = false; /**< Allow only 1 connection */ |
157 | static bool client_connected = false; /**< Allow only 1 connection */ |
141 | 158 | ||
142 | static void draw_glyph(unsigned int x, unsigned int y, bool cursor, |
159 | static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
- | 160 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
|
- | 161 | static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
|
143 | uint8_t *glyphs, uint8_t glyph); |
162 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color); |
- | 163 | ||
144 | static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
164 | static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, |
145 | unsigned int row); |
165 | unsigned int row); |
146 | 166 | ||
147 | 167 | ||
148 | #define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
168 | #define RED(x, bits) ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1)) |
Line 331... | Line 351... | ||
331 | } |
351 | } |
332 | } else { |
352 | } else { |
333 | glyph = 0; |
353 | glyph = 0; |
334 | } |
354 | } |
335 | 355 | ||
336 | draw_glyph(x, y, false, vport->glyphs, glyph); |
356 | (*vport->dglyph)(x, y, false, vport->glyphs, glyph, |
- | 357 | vport->style.fg_color, vport->style.bg_color); |
|
337 | x += FONT_WIDTH; |
358 | x += FONT_WIDTH; |
338 | } |
359 | } |
339 | y += FONT_SCANLINES; |
360 | y += FONT_SCANLINES; |
340 | } |
361 | } |
341 | 362 | ||
Line 374... | Line 395... | ||
374 | unsigned int x; |
395 | unsigned int x; |
375 | 396 | ||
376 | for (x = 0; x < FONT_WIDTH; x++) { |
397 | for (x = 0; x < FONT_WIDTH; x++) { |
377 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
398 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], |
378 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
399 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
379 | ? vport->style.fg_color : vport->style.bg_color); |
- | |
380 | - | ||
381 | uint32_t curcolor; |
400 | ? 0xffffff : 0x000000); |
382 | 401 | ||
383 | if (y < FONT_SCANLINES - 2) |
402 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], |
384 | curcolor = |
- | |
385 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
403 | (fb_font[glyph * FONT_SCANLINES + y] & (1 << (7 - x))) |
386 | ? vport->style.fg_color : vport->style.bg_color; |
- | |
387 | else |
- | |
388 | curcolor = vport->style.fg_color; |
404 | ? 0x000000 : 0xffffff); |
389 | - | ||
390 | screen.rgb_conv(&vport->glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], curcolor); |
- | |
391 | } |
405 | } |
392 | } |
406 | } |
393 | } |
407 | } |
394 | 408 | ||
395 | screen.rgb_conv(vport->bgpixel, vport->style.bg_color); |
409 | screen.rgb_conv(vport->bgpixel, vport->style.bg_color); |
Line 420... | Line 434... | ||
420 | 434 | ||
421 | unsigned int cols = width / FONT_WIDTH; |
435 | unsigned int cols = width / FONT_WIDTH; |
422 | unsigned int rows = height / FONT_SCANLINES; |
436 | unsigned int rows = height / FONT_SCANLINES; |
423 | unsigned int bbsize = cols * rows; |
437 | unsigned int bbsize = cols * rows; |
424 | unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
438 | unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes; |
- | 439 | unsigned int word_size = sizeof(unsigned long); |
|
425 | 440 | ||
426 | uint8_t *backbuf = (uint8_t *) malloc(bbsize); |
441 | uint8_t *backbuf = (uint8_t *) malloc(bbsize); |
427 | if (!backbuf) |
442 | if (!backbuf) |
428 | return ENOMEM; |
443 | return ENOMEM; |
429 | 444 | ||
Line 455... | Line 470... | ||
455 | viewports[i].style.bg_color = DEFAULT_BGCOLOR; |
470 | viewports[i].style.bg_color = DEFAULT_BGCOLOR; |
456 | viewports[i].style.fg_color = DEFAULT_FGCOLOR; |
471 | viewports[i].style.fg_color = DEFAULT_FGCOLOR; |
457 | 472 | ||
458 | viewports[i].glyphs = glyphs; |
473 | viewports[i].glyphs = glyphs; |
459 | viewports[i].bgpixel = bgpixel; |
474 | viewports[i].bgpixel = bgpixel; |
- | 475 | ||
- | 476 | /* |
|
- | 477 | * Conditions necessary to select aligned version: |
|
- | 478 | * |
|
- | 479 | * - word size is divisible by pixelbytes |
|
- | 480 | * - cell scanline size is divisible by word size |
|
- | 481 | * - cell scanlines are word-aligned |
|
- | 482 | */ |
|
- | 483 | if ((word_size % screen.pixelbytes) == 0 && |
|
- | 484 | (FONT_WIDTH * screen.pixelbytes) % word_size == 0 && |
|
- | 485 | (x * screen.pixelbytes) % word_size == 0 && |
|
- | 486 | screen.scanline % word_size == 0) { |
|
- | 487 | ||
- | 488 | viewports[i].dglyph = draw_glyph_aligned; |
|
- | 489 | } else { |
|
- | 490 | viewports[i].dglyph = draw_glyph_fallback; |
|
460 | 491 | } |
|
- | 492 | ||
461 | viewports[i].cur_col = 0; |
493 | viewports[i].cur_col = 0; |
462 | viewports[i].cur_row = 0; |
494 | viewports[i].cur_row = 0; |
463 | viewports[i].cursor_active = false; |
495 | viewports[i].cursor_active = false; |
464 | viewports[i].cursor_shown = false; |
496 | viewports[i].cursor_shown = false; |
465 | 497 | ||
Line 532... | Line 564... | ||
532 | 564 | ||
533 | return true; |
565 | return true; |
534 | } |
566 | } |
535 | 567 | ||
536 | 568 | ||
537 | /** Draw a glyph. |
569 | /** Draw a glyph, takes advantage of alignment. |
538 | * |
570 | * |
539 | * @param x x coordinate of top-left corner on screen. |
- | |
540 | * @param y y coordinate of top-left corner on screen. |
571 | * This version can only be used if the following conditions are met: |
541 | * @param cursor Draw glyph with cursor |
- | |
542 | * @param glyphs Pointer to font bitmap. |
- | |
543 | * @param glyph Code of the glyph to draw. |
- | |
544 | * |
572 | * |
- | 573 | * - word size is divisible by pixelbytes |
|
- | 574 | * - cell scanline size is divisible by word size |
|
- | 575 | * - cell scanlines are word-aligned |
|
- | 576 | * |
|
- | 577 | * It makes use of the pre-rendered mask to process (possibly) several |
|
- | 578 | * pixels at once (word size / pixelbytes pixels at a time are processed) |
|
- | 579 | * making it very fast. Most notably this version is not applicable at 24 bits |
|
- | 580 | * per pixel. |
|
- | 581 | * |
|
- | 582 | * @param x x coordinate of top-left corner on screen. |
|
- | 583 | * @param y y coordinate of top-left corner on screen. |
|
- | 584 | * @param cursor Draw glyph with cursor |
|
- | 585 | * @param glyphs Pointer to font bitmap. |
|
- | 586 | * @param glyph Code of the glyph to draw. |
|
- | 587 | * @param fg_color Foreground color. |
|
- | 588 | * @param bg_color Backgroudn color. |
|
- | 589 | */ |
|
- | 590 | static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, |
|
- | 591 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
|
- | 592 | { |
|
- | 593 | unsigned int i, yd; |
|
- | 594 | unsigned long fg_buf, bg_buf; |
|
- | 595 | unsigned long *maskp, *dp; |
|
- | 596 | unsigned long mask; |
|
- | 597 | unsigned int ww, d_add; |
|
- | 598 | ||
- | 599 | /* |
|
- | 600 | * Prepare a pair of words, one filled with foreground-color |
|
- | 601 | * pattern and the other filled with background-color pattern. |
|
- | 602 | */ |
|
- | 603 | for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) { |
|
- | 604 | screen.rgb_conv(&((uint8_t *)&fg_buf)[i * screen.pixelbytes], |
|
- | 605 | fg_color); |
|
- | 606 | screen.rgb_conv(&((uint8_t *)&bg_buf)[i * screen.pixelbytes], |
|
- | 607 | bg_color); |
|
- | 608 | } |
|
- | 609 | ||
- | 610 | ||
- | 611 | /* Pointer to the current position in the mask. */ |
|
- | 612 | maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)]; |
|
- | 613 | ||
- | 614 | /* Pointer to the current position on the screen. */ |
|
- | 615 | dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)]; |
|
- | 616 | ||
- | 617 | /* Width of the character cell in words. */ |
|
- | 618 | ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long); |
|
- | 619 | ||
- | 620 | /* Offset to add when moving to another screen scanline. */ |
|
- | 621 | d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
- | 622 | ||
- | 623 | for (yd = 0; yd < FONT_SCANLINES; yd++) { |
|
- | 624 | /* |
|
- | 625 | * Now process the cell scanline, combining foreground |
|
- | 626 | * and background color patters using the pre-rendered mask. |
|
- | 627 | */ |
|
- | 628 | for (i = 0; i < ww; i++) { |
|
- | 629 | mask = *maskp++; |
|
- | 630 | *dp++ = (fg_buf & mask) | (bg_buf & ~mask); |
|
- | 631 | } |
|
- | 632 | ||
- | 633 | /* Move to the beginning of the next scanline of the cell. */ |
|
- | 634 | dp = (unsigned long *) ((uint8_t *) dp + d_add); |
|
- | 635 | } |
|
- | 636 | } |
|
- | 637 | ||
- | 638 | /** Draw a glyph, fallback version. |
|
- | 639 | * |
|
- | 640 | * This version does not make use of the pre-rendered mask, it uses |
|
- | 641 | * the font bitmap directly. It works always, but it is slower. |
|
- | 642 | * |
|
- | 643 | * @param x x coordinate of top-left corner on screen. |
|
- | 644 | * @param y y coordinate of top-left corner on screen. |
|
- | 645 | * @param cursor Draw glyph with cursor |
|
- | 646 | * @param glyphs Pointer to font bitmap. |
|
- | 647 | * @param glyph Code of the glyph to draw. |
|
- | 648 | * @param fg_color Foreground color. |
|
- | 649 | * @param bg_color Backgroudn color. |
|
545 | */ |
650 | */ |
546 | static void draw_glyph(unsigned int x, unsigned int y, bool cursor, |
651 | void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, |
547 | uint8_t *glyphs, uint8_t glyph) |
652 | uint8_t *glyphs, uint8_t glyph, uint32_t fg_color, uint32_t bg_color) |
548 | { |
653 | { |
- | 654 | unsigned int i, j, yd; |
|
- | 655 | uint8_t fg_buf[4], bg_buf[4]; |
|
- | 656 | uint8_t *dp, *sp; |
|
549 | unsigned int yd; |
657 | unsigned int d_add; |
- | 658 | uint8_t b; |
|
- | 659 | ||
- | 660 | /* Pre-render 1x the foreground and background color pixels. */ |
|
- | 661 | if (cursor) { |
|
- | 662 | screen.rgb_conv(fg_buf, bg_color); |
|
- | 663 | screen.rgb_conv(bg_buf, fg_color); |
|
- | 664 | } else { |
|
- | 665 | screen.rgb_conv(fg_buf, fg_color); |
|
- | 666 | screen.rgb_conv(bg_buf, bg_color); |
|
550 | 667 | } |
|
- | 668 | ||
- | 669 | /* Pointer to the current position on the screen. */ |
|
- | 670 | dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)]; |
|
- | 671 | ||
- | 672 | /* Offset to add when moving to another screen scanline. */ |
|
- | 673 | d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes; |
|
- | 674 | ||
551 | for (yd = 0; yd < FONT_SCANLINES; yd++) |
675 | for (yd = 0; yd < FONT_SCANLINES; yd++) { |
- | 676 | /* Byte containing bits of the glyph scanline. */ |
|
552 | memcpy(&screen.fb_addr[FB_POS(x, y + yd)], |
677 | b = fb_font[glyph * FONT_SCANLINES + yd]; |
- | 678 | ||
- | 679 | for (i = 0; i < FONT_WIDTH; i++) { |
|
- | 680 | /* Choose color based on the current bit. */ |
|
- | 681 | sp = (b & 0x80) ? fg_buf : bg_buf; |
|
- | 682 | ||
- | 683 | /* Copy the pixel. */ |
|
- | 684 | for (j = 0; j < screen.pixelbytes; j++) { |
|
- | 685 | *dp++ = *sp++; |
|
- | 686 | } |
|
- | 687 | ||
- | 688 | /* Move to the next bit. */ |
|
- | 689 | b = b << 1; |
|
- | 690 | } |
|
- | 691 | ||
553 | &glyphs[GLYPH_POS(glyph, yd, cursor)], screen.glyphscanline); |
692 | /* Move to the beginning of the next scanline of the cell. */ |
- | 693 | dp += d_add; |
|
- | 694 | } |
|
554 | } |
695 | } |
555 | 696 | ||
556 | /** Draw glyph at specified position in viewport. |
697 | /** Draw glyph at specified position in viewport. |
557 | * |
698 | * |
558 | * @param vport Viewport identification |
699 | * @param vport Viewport identification |
Line 567... | Line 708... | ||
567 | unsigned int x = vport->x + COL2X(col); |
708 | unsigned int x = vport->x + COL2X(col); |
568 | unsigned int y = vport->y + ROW2Y(row); |
709 | unsigned int y = vport->y + ROW2Y(row); |
569 | uint8_t glyph; |
710 | uint8_t glyph; |
570 | 711 | ||
571 | glyph = vport->backbuf[BB_POS(vport, col, row)]; |
712 | glyph = vport->backbuf[BB_POS(vport, col, row)]; |
572 | draw_glyph(x, y, cursor, vport->glyphs, glyph); |
- | |
573 | } |
- | |
574 | 713 | ||
- | 714 | (*vport->dglyph)(x, y, cursor, vport->glyphs, glyph, |
|
- | 715 | vport->style.fg_color, vport->style.bg_color); |
|
- | 716 | } |
|
575 | 717 | ||
576 | /** Hide cursor if it is shown |
718 | /** Hide cursor if it is shown |
577 | * |
719 | * |
578 | */ |
720 | */ |
579 | static void cursor_hide(viewport_t *vport) |
721 | static void cursor_hide(viewport_t *vport) |
Line 1336... | Line 1478... | ||
1336 | retval = EOK; |
1478 | retval = EOK; |
1337 | break; |
1479 | break; |
1338 | case FB_SET_STYLE: |
1480 | case FB_SET_STYLE: |
1339 | vport->style.fg_color = IPC_GET_ARG1(call); |
1481 | vport->style.fg_color = IPC_GET_ARG1(call); |
1340 | vport->style.bg_color = IPC_GET_ARG2(call); |
1482 | vport->style.bg_color = IPC_GET_ARG2(call); |
1341 | render_glyphs(vport); |
- | |
1342 | retval = EOK; |
1483 | retval = EOK; |
1343 | break; |
1484 | break; |
1344 | case FB_GET_RESOLUTION: |
1485 | case FB_GET_RESOLUTION: |
1345 | ipc_answer_2(callid, EOK, screen.xres, screen.yres); |
1486 | ipc_answer_2(callid, EOK, screen.xres, screen.yres); |
1346 | continue; |
1487 | continue; |