source: mainline/uspace/srv/fb/fb.c@ b74959bd

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

Modify ipc_answer_*() to make use of all six syscall arguments. The recommended
means of answering calls is via the ipc_answer_m() macros (where m denotes the
number of return arguments) that automatically decide between the fast register
version or the slow universal version of ipc_answer().

  • Property mode set to 100644
File size: 31.3 KB
RevLine 
[afa6e74]1/*
[df4ed85]2 * Copyright (c) 2006 Jakub Vana
3 * Copyright (c) 2006 Ondrej Palkovsky
[afa6e74]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
[231a60a]30/**
31 * @defgroup fb Graphical framebuffer
32 * @brief HelenOS graphical framebuffer.
[ce5bcb4]33 * @ingroup fbs
34 * @{
35 */
[06e1e95]36
[ce5bcb4]37/** @file
38 */
39
[afa6e74]40#include <stdlib.h>
[7f5b37a]41#include <unistd.h>
42#include <string.h>
[afa6e74]43#include <ddi.h>
44#include <sysinfo.h>
45#include <align.h>
46#include <as.h>
47#include <ipc/fb.h>
48#include <ipc/ipc.h>
49#include <ipc/ns.h>
[7f5b37a]50#include <ipc/services.h>
[afa6e74]51#include <kernel/errno.h>
[2bc137c2]52#include <kernel/genarch/fb/visuals.h>
[80649a91]53#include <async.h>
[2bc137c2]54#include <bool.h>
[83b1d61]55
[a2cd194]56#include "font-8x16.h"
[afa6e74]57#include "fb.h"
[83b1d61]58#include "main.h"
59#include "../console/screenbuffer.h"
[90f5d64]60#include "ppm.h"
[afa6e74]61
[2ce520c]62#include "pointer.xbm"
63#include "pointer_mask.xbm"
64
[7284260]65#define DEFAULT_BGCOLOR 0xf0f0f0
66#define DEFAULT_FGCOLOR 0x0
[afa6e74]67
68/***************************************************************/
69/* Pixel specific fuctions */
70
[a7d2d78]71typedef void (*conv2scr_fn_t)(void *, int);
72typedef int (*conv2rgb_fn_t)(void *);
[afa6e74]73
[a2ae4f4]74struct {
[253f35a1]75 uint8_t *fbaddress;
[afa6e74]76
[253f35a1]77 unsigned int xres;
78 unsigned int yres;
79 unsigned int scanline;
80 unsigned int pixelbytes;
81 unsigned int invert_colors;
[afa6e74]82
[a7d2d78]83 conv2scr_fn_t rgb2scr;
84 conv2rgb_fn_t scr2rgb;
[a2ae4f4]85} screen;
[afa6e74]86
[a2ae4f4]87typedef struct {
88 int initialized;
89 unsigned int x, y;
90 unsigned int width, height;
[afa6e74]91
[a2ae4f4]92 /* Text support in window */
93 unsigned int rows, cols;
94 /* Style for text printing */
[6b5111a]95 style_t style;
[a2ae4f4]96 /* Auto-cursor position */
[88c3151]97 int cursor_active, cur_col, cur_row;
[49d072e]98 int cursor_shown;
[e92aabf]99 /* Double buffering */
[afbe96a]100 uint8_t *dbdata;
[e92aabf]101 unsigned int dboffset;
102 unsigned int paused;
[a2ae4f4]103} viewport_t;
104
[1fd7700]105#define MAX_ANIM_LEN 8
106#define MAX_ANIMATIONS 4
107typedef struct {
108 int initialized;
109 int enabled;
110 unsigned int vp;
111
112 unsigned int pos;
113 unsigned int animlen;
114 unsigned int pixmaps[MAX_ANIM_LEN];
115} animation_t;
116static animation_t animations[MAX_ANIMATIONS];
117static int anims_enabled;
118
[429acb9]119/** Maximum number of saved pixmaps
120 * Pixmap is a saved rectangle
121 */
122#define MAX_PIXMAPS 256
123typedef struct {
124 unsigned int width;
125 unsigned int height;
[afbe96a]126 uint8_t *data;
[429acb9]127} pixmap_t;
128static pixmap_t pixmaps[MAX_PIXMAPS];
129
130/* Viewport is a rectangular area on the screen */
[a2ae4f4]131#define MAX_VIEWPORTS 128
132static viewport_t viewports[128];
133
134/* Allow only 1 connection */
135static int client_connected = 0;
[afa6e74]136
137#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
138#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
139#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
140
[a2ae4f4]141#define COL_WIDTH 8
142#define ROW_BYTES (screen.scanline * FONT_SCANLINES)
[afa6e74]143
[a2ae4f4]144#define POINTPOS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes)
[afa6e74]145
[253f35a1]146static inline int COLOR(int color)
147{
148 return screen.invert_colors ? ~color : color;
149}
150
[a7d2d78]151/* Conversion routines between different color representations */
[d7baee6]152static void
153rgb_byte0888(void *dst, int rgb)
[afa6e74]154{
[a7d2d78]155 *(int *)dst = rgb;
[afa6e74]156}
157
[d7baee6]158static int
159byte0888_rgb(void *src)
[afa6e74]160{
[a7d2d78]161 return (*(int *)src) & 0xffffff;
[afa6e74]162}
163
[d7baee6]164static void
165bgr_byte0888(void *dst, int rgb)
[ccb0cbc]166{
[00bb6965]167 *((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 |
[b74959bd]168 RED(rgb, 8);
[ccb0cbc]169}
170
[d7baee6]171static int
172byte0888_bgr(void *src)
[ccb0cbc]173{
174 int color = *(uint32_t *)(src);
[d7baee6]175 return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) |
[b74959bd]176 ((color >> 16) & 0xff);
[ccb0cbc]177}
178
[d7baee6]179static void
180rgb_byte888(void *dst, int rgb)
[afa6e74]181{
[afbe96a]182 uint8_t *scr = dst;
[d7e3f1ad]183#if defined(FB_INVERT_ENDIAN)
[a7d2d78]184 scr[0] = RED(rgb, 8);
185 scr[1] = GREEN(rgb, 8);
186 scr[2] = BLUE(rgb, 8);
[afa6e74]187#else
[a7d2d78]188 scr[2] = RED(rgb, 8);
189 scr[1] = GREEN(rgb, 8);
190 scr[0] = BLUE(rgb, 8);
[afa6e74]191#endif
192}
193
[d7baee6]194static int
195byte888_rgb(void *src)
[afa6e74]196{
[afbe96a]197 uint8_t *scr = src;
[d7e3f1ad]198#if defined(FB_INVERT_ENDIAN)
[a7d2d78]199 return scr[0] << 16 | scr[1] << 8 | scr[2];
[afa6e74]200#else
[a7d2d78]201 return scr[2] << 16 | scr[1] << 8 | scr[0];
202#endif
[afa6e74]203}
204
[2bc137c2]205/** 16-bit depth (5:5:5) */
[d7baee6]206static void
207rgb_byte555(void *dst, int rgb)
[2bc137c2]208{
209 /* 5-bit, 5-bits, 5-bits */
[00bb6965]210 *((uint16_t *)(dst)) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 |
[b74959bd]211 BLUE(rgb, 5);
[2bc137c2]212}
213
214/** 16-bit depth (5:5:5) */
[d7baee6]215static int
216byte555_rgb(void *src)
[2bc137c2]217{
218 int color = *(uint16_t *)(src);
[d7baee6]219 return (((color >> 10) & 0x1f) << (16 + 3)) |
[b74959bd]220 (((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);
[2bc137c2]221}
222
[a7d2d78]223/** 16-bit depth (5:6:5) */
[d7baee6]224static void
225rgb_byte565(void *dst, int rgb)
[afa6e74]226{
227 /* 5-bit, 6-bits, 5-bits */
[00bb6965]228 *((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 |
[b74959bd]229 BLUE(rgb, 5);
[afa6e74]230}
231
[a7d2d78]232/** 16-bit depth (5:6:5) */
[d7baee6]233static int
234byte565_rgb(void *src)
[afa6e74]235{
[afbe96a]236 int color = *(uint16_t *)(src);
[d7baee6]237 return (((color >> 11) & 0x1f) << (16 + 3)) |
[b74959bd]238 (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
[afa6e74]239}
240
241/** Put pixel - 8-bit depth (3:2:3) */
[d7baee6]242static void
243rgb_byte8(void *dst, int rgb)
[afa6e74]244{
[afbe96a]245 *(uint8_t *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3);
[afa6e74]246}
247
248/** Return pixel color - 8-bit depth (3:2:3) */
[d7baee6]249static int
250byte8_rgb(void *src)
[afa6e74]251{
[afbe96a]252 int color = *(uint8_t *)src;
[d7baee6]253 return (((color >> 5) & 0x7) << (16 + 5)) |
[b74959bd]254 (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
[afa6e74]255}
256
[1180a88e]257/** Put pixel into viewport
258 *
[096ba7a]259 * @param vport Viewport identification
[1180a88e]260 * @param x X coord relative to viewport
261 * @param y Y coord relative to viewport
262 * @param color RGB color
263 */
[d7baee6]264static void
265putpixel(viewport_t *vport, unsigned int x, unsigned int y, int color)
[a2ae4f4]266{
[bd02038]267 int dx = vport->x + x;
268 int dy = vport->y + y;
[e92aabf]269
[bd02038]270 if (! (vport->paused && vport->dbdata))
[d7baee6]271 (*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)],
[b74959bd]272 COLOR(color));
[e92aabf]273
[bd02038]274 if (vport->dbdata) {
275 int dline = (y + vport->dboffset) % vport->height;
276 int doffset = screen.pixelbytes * (dline * vport->width + x);
[253f35a1]277 (*screen.rgb2scr)(&vport->dbdata[doffset], COLOR(color));
[e92aabf]278 }
[a2ae4f4]279}
[e92aabf]280
[1180a88e]281/** Get pixel from viewport */
[d7baee6]282static int
283getpixel(viewport_t *vport, unsigned int x, unsigned int y)
[a2ae4f4]284{
[bd02038]285 int dx = vport->x + x;
286 int dy = vport->y + y;
[a7d2d78]287
[d7baee6]288 return COLOR((*screen.scr2rgb)(&screen.fbaddress[POINTPOS(dx, dy)]));
[a2ae4f4]289}
290
[d7baee6]291static inline void
292putpixel_mem(char *mem, unsigned int x, unsigned int y, int color)
[afa6e74]293{
[b74959bd]294 (*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color));
[afa6e74]295}
296
[d7baee6]297static void
298draw_rectangle(viewport_t *vport, unsigned int sx, unsigned int sy,
[00bb6965]299 unsigned int width, unsigned int height, int color)
[67ec84b]300{
301 unsigned int x, y;
[0a9a324]302 static void *tmpline;
303
304 if (!tmpline)
[b74959bd]305 tmpline = malloc(screen.scanline * screen.pixelbytes);
[67ec84b]306
307 /* Clear first line */
308 for (x = 0; x < width; x++)
[0a9a324]309 putpixel_mem(tmpline, x, 0, color);
[67ec84b]310
[bd02038]311 if (!vport->paused) {
[e92aabf]312 /* Recompute to screen coords */
[bd02038]313 sx += vport->x;
314 sy += vport->y;
[e92aabf]315 /* Copy the rest */
316 for (y = sy;y < sy+height; y++)
317 memcpy(&screen.fbaddress[POINTPOS(sx,y)], tmpline,
[b74959bd]318 screen.pixelbytes * width);
[e92aabf]319 }
[bd02038]320 if (vport->dbdata) {
[00bb6965]321 for (y = sy; y < sy + height; y++) {
[bd02038]322 int rline = (y + vport->dboffset) % vport->height;
[00bb6965]323 int rpos = (rline * vport->width + sx) *
[b74959bd]324 screen.pixelbytes;
[00bb6965]325 memcpy(&vport->dbdata[rpos], tmpline,
[b74959bd]326 screen.pixelbytes * width);
[e92aabf]327 }
328 }
[67ec84b]329
330}
331
[a2ae4f4]332/** Fill viewport with background color */
[d7baee6]333static void
334clear_port(viewport_t *vport)
[afa6e74]335{
[00bb6965]336 draw_rectangle(vport, 0, 0, vport->width, vport->height,
[b74959bd]337 vport->style.bg_color);
[afa6e74]338}
339
[e92aabf]340/** Scroll unbuffered viewport up/down
[a2ae4f4]341 *
[096ba7a]342 * @param vport Viewport to scroll
343 * @param lines Positive number - scroll up, negative - scroll down
[a2ae4f4]344 */
[d7baee6]345static void
346scroll_port_nodb(viewport_t *vport, int lines)
[afa6e74]347{
[a2ae4f4]348 int y;
[e92aabf]349
350 if (lines > 0) {
[00bb6965]351 for (y = vport->y; y < vport->y+vport->height - lines; y++)
[67ec84b]352 memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
[b74959bd]353 &screen.fbaddress[POINTPOS(vport->x,y + lines)],
354 screen.pixelbytes * vport->width);
[00bb6965]355 draw_rectangle(vport, 0, vport->height - lines, vport->width,
[b74959bd]356 lines, vport->style.bg_color);
[e92aabf]357 } else if (lines < 0) {
358 lines = -lines;
[b74959bd]359 for (y = vport->y + vport->height-1; y >= vport->y + lines; y--)
[67ec84b]360 memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
[b74959bd]361 &screen.fbaddress[POINTPOS(vport->x,y - lines)],
362 screen.pixelbytes * vport->width);
[00bb6965]363 draw_rectangle(vport, 0, 0, vport->width, lines,
[b74959bd]364 vport->style.bg_color);
[e92aabf]365 }
366}
367
368/** Refresh given viewport from double buffer */
[d7baee6]369static void
370refresh_viewport_db(viewport_t *vport)
[e92aabf]371{
372 unsigned int y, srcy, srcoff, dsty, dstx;
373
[bd02038]374 for (y = 0; y < vport->height; y++) {
375 srcy = (y + vport->dboffset) % vport->height;
376 srcoff = (vport->width * srcy) * screen.pixelbytes;
[e92aabf]377
[bd02038]378 dstx = vport->x;
379 dsty = vport->y + y;
[e92aabf]380
381 memcpy(&screen.fbaddress[POINTPOS(dstx,dsty)],
[b74959bd]382 &vport->dbdata[srcoff], vport->width * screen.pixelbytes);
[a2ae4f4]383 }
[afa6e74]384}
385
[e92aabf]386/** Scroll viewport that has double buffering enabled */
[d7baee6]387static void
388scroll_port_db(viewport_t *vport, int lines)
[e92aabf]389{
[bd02038]390 ++vport->paused;
[e92aabf]391 if (lines > 0) {
[bd02038]392 draw_rectangle(vport, 0, 0, vport->width, lines,
[b74959bd]393 vport->style.bg_color);
[bd02038]394 vport->dboffset += lines;
395 vport->dboffset %= vport->height;
[e92aabf]396 } else if (lines < 0) {
397 lines = -lines;
[b74959bd]398 draw_rectangle(vport, 0, vport->height-lines, vport->width,
399 lines, vport->style.bg_color);
[e92aabf]400
[bd02038]401 if (vport->dboffset < lines)
402 vport->dboffset += vport->height;
403 vport->dboffset -= lines;
[e92aabf]404 }
405
[bd02038]406 --vport->paused;
[e92aabf]407
[bd02038]408 refresh_viewport_db(vport);
[e92aabf]409}
410
411/** Scrolls viewport given number of lines */
[d7baee6]412static void
413scroll_port(viewport_t *vport, int lines)
[e92aabf]414{
[bd02038]415 if (vport->dbdata)
416 scroll_port_db(vport, lines);
[e92aabf]417 else
[bd02038]418 scroll_port_nodb(vport, lines);
[e92aabf]419
420}
421
[d7baee6]422static void
423invert_pixel(viewport_t *vport, unsigned int x, unsigned int y)
[afa6e74]424{
[bd02038]425 putpixel(vport, x, y, ~getpixel(vport, x, y));
[afa6e74]426}
427
428
429/***************************************************************/
430/* Character-console functions */
431
[d530237a]432/** Draw character at given position
433 *
[096ba7a]434 * @param vport Viewport where the character is printed
[d530237a]435 * @param sx Coordinates of top-left of the character
436 * @param sy Coordinates of top-left of the character
437 * @param style Color of the character
438 * @param transparent If false, print background color
439 */
[d7baee6]440static void
[b74959bd]441draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, unsigned int sy,
442 style_t style, int transparent)
[afa6e74]443{
[6b5111a]444 int i;
[afa6e74]445 unsigned int y;
[6b5111a]446 unsigned int glline;
447
448 for (y = 0; y < FONT_SCANLINES; y++) {
449 glline = fb_font[glyph * FONT_SCANLINES + y];
450 for (i = 0; i < 8; i++) {
451 if (glline & (1 << (7 - i)))
[b74959bd]452 putpixel(vport, sx + i, sy + y, style.fg_color);
[d530237a]453 else if (!transparent)
[b74959bd]454 putpixel(vport, sx + i, sy + y, style.bg_color);
[6b5111a]455 }
456 }
[afa6e74]457}
458
459/** Invert character at given position */
[d7baee6]460static void
461invert_char(viewport_t *vport,unsigned int row, unsigned int col)
[afa6e74]462{
463 unsigned int x;
464 unsigned int y;
465
466 for (x = 0; x < COL_WIDTH; x++)
467 for (y = 0; y < FONT_SCANLINES; y++)
[00bb6965]468 invert_pixel(vport, col * COL_WIDTH + x, row *
[b74959bd]469 FONT_SCANLINES + y);
[afa6e74]470}
471
472/***************************************************************/
473/* Stdout specific functions */
474
475
[a2ae4f4]476/** Create new viewport
[afa6e74]477 *
[a2ae4f4]478 * @return New viewport number
[afa6e74]479 */
[d7baee6]480static int
481viewport_create(unsigned int x, unsigned int y,unsigned int width,
[00bb6965]482 unsigned int height)
[afa6e74]483{
[a2ae4f4]484 int i;
485
[d7baee6]486 for (i = 0; i < MAX_VIEWPORTS; i++) {
[a2ae4f4]487 if (!viewports[i].initialized)
[afa6e74]488 break;
489 }
[a2ae4f4]490 if (i == MAX_VIEWPORTS)
491 return ELIMIT;
492
493 viewports[i].x = x;
494 viewports[i].y = y;
495 viewports[i].width = width;
496 viewports[i].height = height;
[afa6e74]497
[a2ae4f4]498 viewports[i].rows = height / FONT_SCANLINES;
499 viewports[i].cols = width / COL_WIDTH;
500
[6b5111a]501 viewports[i].style.bg_color = DEFAULT_BGCOLOR;
502 viewports[i].style.fg_color = DEFAULT_FGCOLOR;
[afa6e74]503
[c1d2c9d]504 viewports[i].cur_col = 0;
505 viewports[i].cur_row = 0;
506 viewports[i].cursor_active = 0;
507
[88c3151]508 viewports[i].initialized = 1;
509
[a2ae4f4]510 return i;
[afa6e74]511}
512
513/** Initialize framebuffer as a chardev output device
514 *
[2bc137c2]515 * @param addr Address of theframebuffer
516 * @param xres Screen width in pixels
517 * @param yres Screen height in pixels
518 * @param visual Bits per pixel (8, 16, 24, 32)
519 * @param scan Bytes per one scanline
[253f35a1]520 * @param invert_colors Inverted colors.
[afa6e74]521 *
522 */
[d7baee6]523static bool
524screen_init(void *addr, unsigned int xres, unsigned int yres,
[00bb6965]525 unsigned int scan, unsigned int visual, bool invert_colors)
[afa6e74]526{
[2bc137c2]527 switch (visual) {
528 case VISUAL_INDIRECT_8:
529 screen.rgb2scr = rgb_byte8;
530 screen.scr2rgb = byte8_rgb;
[775df25]531 screen.pixelbytes = 1;
532 break;
[2bc137c2]533 case VISUAL_RGB_5_5_5:
534 screen.rgb2scr = rgb_byte555;
535 screen.scr2rgb = byte555_rgb;
[775df25]536 screen.pixelbytes = 2;
537 break;
[2bc137c2]538 case VISUAL_RGB_5_6_5:
539 screen.rgb2scr = rgb_byte565;
540 screen.scr2rgb = byte565_rgb;
541 screen.pixelbytes = 2;
[775df25]542 break;
[2bc137c2]543 case VISUAL_RGB_8_8_8:
544 screen.rgb2scr = rgb_byte888;
545 screen.scr2rgb = byte888_rgb;
546 screen.pixelbytes = 3;
547 break;
548 case VISUAL_RGB_8_8_8_0:
549 screen.rgb2scr = rgb_byte888;
550 screen.scr2rgb = byte888_rgb;
551 screen.pixelbytes = 4;
552 break;
553 case VISUAL_RGB_0_8_8_8:
554 screen.rgb2scr = rgb_byte0888;
555 screen.scr2rgb = byte0888_rgb;
[775df25]556 screen.pixelbytes = 4;
557 break;
[ccb0cbc]558 case VISUAL_BGR_0_8_8_8:
559 screen.rgb2scr = bgr_byte0888;
560 screen.scr2rgb = byte0888_bgr;
561 screen.pixelbytes = 4;
562 break;
[2bc137c2]563 default:
564 return false;
[afa6e74]565 }
566
[a2ae4f4]567 screen.fbaddress = (unsigned char *) addr;
568 screen.xres = xres;
569 screen.yres = yres;
570 screen.scanline = scan;
[253f35a1]571 screen.invert_colors = invert_colors;
[afa6e74]572
[a2ae4f4]573 /* Create first viewport */
[2bc137c2]574 viewport_create(0, 0, xres, yres);
575
576 return true;
[afa6e74]577}
578
[429acb9]579/** Hide cursor if it is shown */
[d7baee6]580static void
581cursor_hide(viewport_t *vport)
[49d072e]582{
583 if (vport->cursor_active && vport->cursor_shown) {
[bd02038]584 invert_char(vport, vport->cur_row, vport->cur_col);
[49d072e]585 vport->cursor_shown = 0;
586 }
587}
588
[429acb9]589/** Show cursor if cursor showing is enabled */
[d7baee6]590static void
591cursor_print(viewport_t *vport)
[49d072e]592{
593 /* Do not check for cursor_shown */
594 if (vport->cursor_active) {
[bd02038]595 invert_char(vport, vport->cur_row, vport->cur_col);
[49d072e]596 vport->cursor_shown = 1;
597 }
598}
599
[429acb9]600/** Invert cursor, if it is enabled */
[d7baee6]601static void
602cursor_blink(viewport_t *vport)
[49d072e]603{
604 if (vport->cursor_shown)
[bd02038]605 cursor_hide(vport);
[49d072e]606 else
[bd02038]607 cursor_print(vport);
[49d072e]608}
609
[1180a88e]610/** Draw character at given position relative to viewport
611 *
[096ba7a]612 * @param vport Viewport identification
[1180a88e]613 * @param c Character to print
614 * @param row Screen position relative to viewport
615 * @param col Screen position relative to viewport
[d530237a]616 * @param transparent If false, print background color with character
[1180a88e]617 */
[d7baee6]618static void
619draw_char(viewport_t *vport, char c, unsigned int row, unsigned int col,
620 style_t style, int transparent)
[88c3151]621{
[49d072e]622 /* Optimize - do not hide cursor if we are going to overwrite it */
623 if (vport->cursor_active && vport->cursor_shown &&
624 (vport->cur_col != col || vport->cur_row != row))
[bd02038]625 invert_char(vport, vport->cur_row, vport->cur_col);
[88c3151]626
[00bb6965]627 draw_glyph(vport, c, col * COL_WIDTH, row * FONT_SCANLINES, style,
[b74959bd]628 transparent);
[c1d2c9d]629
630 vport->cur_col = col;
631 vport->cur_row = row;
632
633 vport->cur_col++;
[00bb6965]634 if (vport->cur_col >= vport->cols) {
[c1d2c9d]635 vport->cur_col = 0;
636 vport->cur_row++;
637 if (vport->cur_row >= vport->rows)
638 vport->cur_row--;
[88c3151]639 }
[bd02038]640 cursor_print(vport);
[88c3151]641}
642
[429acb9]643/** Draw text data to viewport
644 *
[096ba7a]645 * @param vport Viewport id
[429acb9]646 * @param data Text data fitting exactly into viewport
647 */
[d7baee6]648static void
649draw_text_data(viewport_t *vport, keyfield_t *data)
[83b1d61]650{
651 int i;
[58fce89]652 int col,row;
[83b1d61]653
[bd02038]654 clear_port(vport);
[00bb6965]655 for (i = 0; i < vport->cols * vport->rows; i++) {
656 if (data[i].character == ' ' && style_same(data[i].style,
[b74959bd]657 vport->style))
[83b1d61]658 continue;
[58fce89]659 col = i % vport->cols;
660 row = i / vport->cols;
[00bb6965]661 draw_glyph(vport, data[i].character, col * COL_WIDTH, row *
[b74959bd]662 FONT_SCANLINES, data[i].style, style_same(data[i].style,
663 vport->style));
[83b1d61]664 }
[bd02038]665 cursor_print(vport);
[83b1d61]666}
667
[a7d2d78]668/** Return first free pixmap */
[d7baee6]669static int
670find_free_pixmap(void)
[a7d2d78]671{
672 int i;
673
[d7baee6]674 for (i = 0;i < MAX_PIXMAPS;i++)
[a7d2d78]675 if (!pixmaps[i].data)
676 return i;
677 return -1;
678}
679
[d7baee6]680static void
681putpixel_pixmap(int pm, unsigned int x, unsigned int y, int color)
[a7d2d78]682{
683 pixmap_t *pmap = &pixmaps[pm];
684 int pos = (y * pmap->width + x) * screen.pixelbytes;
685
[253f35a1]686 (*screen.rgb2scr)(&pmap->data[pos],COLOR(color));
[a7d2d78]687}
688
689/** Create a new pixmap and return appropriate ID */
[d7baee6]690static int
691shm2pixmap(unsigned char *shm, size_t size)
[a7d2d78]692{
693 int pm;
694 pixmap_t *pmap;
695
696 pm = find_free_pixmap();
697 if (pm == -1)
698 return ELIMIT;
699 pmap = &pixmaps[pm];
700
701 if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
702 return EINVAL;
703
704 pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
705 if (!pmap->data)
706 return ENOMEM;
707
708 ppm_draw(shm, size, 0, 0, pmap->width, pmap->height,
[b74959bd]709 (putpixel_cb_t)putpixel_pixmap, (void *)pm);
[a7d2d78]710
711 return pm;
712}
713
[429acb9]714/** Handle shared memory communication calls
715 *
716 * Protocol for drawing pixmaps:
717 * - FB_PREPARE_SHM(client shm identification)
[00bb6965]718 * - IPC_M_AS_AREA_SEND
[429acb9]719 * - FB_DRAW_PPM(startx,starty)
720 * - FB_DROP_SHM
721 *
722 * Protocol for text drawing
[00bb6965]723 * - IPC_M_AS_AREA_SEND
[429acb9]724 * - FB_DRAW_TEXT_DATA
725 *
726 * @param callid Callid of the current call
727 * @param call Current call data
728 * @param vp Active viewport
729 * @return 0 if the call was not handled byt this function, 1 otherwise
730 *
731 * note: this function is not threads safe, you would have
732 * to redefine static variables with __thread
733 */
[d7baee6]734static int
735shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
[90f5d64]736{
737 static keyfield_t *interbuffer = NULL;
738 static size_t intersize = 0;
739
[153a209]740 static unsigned char *shm = NULL;
[a7d2d78]741 static ipcarg_t shm_id = 0;
742 static size_t shm_size;
[90f5d64]743
744 int handled = 1;
745 int retval = 0;
746 viewport_t *vport = &viewports[vp];
[d7baee6]747 unsigned int x, y;
[90f5d64]748
749 switch (IPC_GET_METHOD(*call)) {
750 case IPC_M_AS_AREA_SEND:
751 /* We accept one area for data interchange */
[a7d2d78]752 if (IPC_GET_ARG1(*call) == shm_id) {
[2057572]753 void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
[a7d2d78]754 shm_size = IPC_GET_ARG2(*call);
[b74959bd]755 if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
[a7d2d78]756 shm = dest;
[90f5d64]757 else
[a7d2d78]758 shm_id = 0;
759 if (shm[0] != 'P')
[90f5d64]760 while (1)
761 ;
762 return 1;
763 } else {
764 intersize = IPC_GET_ARG2(*call);
[f8ddd17]765 receive_comm_area(callid, call, (void *) &interbuffer);
[90f5d64]766 }
767 return 1;
768 case FB_PREPARE_SHM:
[a7d2d78]769 if (shm_id)
[90f5d64]770 retval = EBUSY;
771 else
[a7d2d78]772 shm_id = IPC_GET_ARG1(*call);
[90f5d64]773 break;
774
775 case FB_DROP_SHM:
[a7d2d78]776 if (shm) {
777 as_area_destroy(shm);
778 shm = NULL;
[90f5d64]779 }
[a7d2d78]780 shm_id = 0;
781 break;
782
783 case FB_SHM2PIXMAP:
784 if (!shm) {
785 retval = EINVAL;
786 break;
787 }
788 retval = shm2pixmap(shm, shm_size);
[90f5d64]789 break;
790 case FB_DRAW_PPM:
[a7d2d78]791 if (!shm) {
[90f5d64]792 retval = EINVAL;
793 break;
794 }
795 x = IPC_GET_ARG1(*call);
796 y = IPC_GET_ARG2(*call);
797 if (x > vport->width || y > vport->height) {
798 retval = EINVAL;
799 break;
800 }
801
[00bb6965]802 ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
[b74959bd]803 IPC_GET_ARG2(*call), vport->width - x, vport->height - y,
804 (putpixel_cb_t)putpixel, vport);
[90f5d64]805 break;
806 case FB_DRAW_TEXT_DATA:
807 if (!interbuffer) {
808 retval = EINVAL;
809 break;
810 }
[00bb6965]811 if (intersize < vport->cols * vport->rows *
[b74959bd]812 sizeof(*interbuffer)) {
[90f5d64]813 retval = EINVAL;
814 break;
815 }
[bd02038]816 draw_text_data(vport, interbuffer);
[90f5d64]817 break;
818 default:
819 handled = 0;
820 }
821
822 if (handled)
[b74959bd]823 ipc_answer_0(callid, retval);
[90f5d64]824 return handled;
825}
[83b1d61]826
[d7baee6]827static void
828copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
[429acb9]829{
[153a209]830 int y;
[07bd231e]831 int tmp, srcrowsize;
832 int realwidth, realheight, realrowsize;
[2ce520c]833 int width = vport->width;
834 int height = vport->height;
835
836 if (width + vport->x > screen.xres)
837 width = screen.xres - vport->x;
[07bd231e]838 if (height + vport->y > screen.yres)
[2ce520c]839 height = screen.yres - vport->y;
[07bd231e]840
841 realwidth = pmap->width <= width ? pmap->width : width;
842 realheight = pmap->height <= height ? pmap->height : height;
[2ce520c]843
[07bd231e]844 srcrowsize = vport->width * screen.pixelbytes;
845 realrowsize = realwidth * screen.pixelbytes;
846
847 for (y = 0; y < realheight; y++) {
[d7baee6]848 tmp = (vport->y + y) * screen.scanline +
[b74959bd]849 vport->x * screen.pixelbytes;
[07bd231e]850 memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp,
[b74959bd]851 realrowsize);
[2ce520c]852 }
853}
854
855/** Save viewport to pixmap */
[d7baee6]856static int
857save_vp_to_pixmap(viewport_t *vport)
[2ce520c]858{
859 int pm;
860 pixmap_t *pmap;
[429acb9]861
862 pm = find_free_pixmap();
863 if (pm == -1)
864 return ELIMIT;
865
866 pmap = &pixmaps[pm];
867 pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
868 if (!pmap->data)
869 return ENOMEM;
870
871 pmap->width = vport->width;
872 pmap->height = vport->height;
[2ce520c]873
874 copy_vp_to_pixmap(vport, pmap);
[429acb9]875
876 return pm;
877}
878
879/** Draw pixmap on screen
880 *
881 * @param vp Viewport to draw on
882 * @param pm Pixmap identifier
883 */
884static int draw_pixmap(int vp, int pm)
885{
886 pixmap_t *pmap = &pixmaps[pm];
887 viewport_t *vport = &viewports[vp];
[153a209]888 int y;
[429acb9]889 int tmp, srcrowsize;
890 int realwidth, realheight, realrowsize;
[2ce520c]891 int width = vport->width;
892 int height = vport->height;
893
894 if (width + vport->x > screen.xres)
895 width = screen.xres - vport->x;
896 if (height + vport->y > screen.yres)
897 height = screen.yres - vport->y;
[429acb9]898
899 if (!pmap->data)
900 return EINVAL;
901
[2ce520c]902 realwidth = pmap->width <= width ? pmap->width : width;
903 realheight = pmap->height <= height ? pmap->height : height;
[429acb9]904
905 srcrowsize = vport->width * screen.pixelbytes;
906 realrowsize = realwidth * screen.pixelbytes;
907
[d7baee6]908 for (y = 0; y < realheight; y++) {
909 tmp = (vport->y + y) * screen.scanline +
[b74959bd]910 vport->x * screen.pixelbytes;
[00bb6965]911 memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize,
[b74959bd]912 realrowsize);
[429acb9]913 }
[6118e5f6]914 return 0;
[429acb9]915}
916
[1fd7700]917/** Tick animation one step forward */
[d7baee6]918static void
919anims_tick(void)
[1fd7700]920{
921 int i;
922 static int counts = 0;
923
924 /* Limit redrawing */
[00bb6965]925 counts = (counts + 1) % 8;
[1fd7700]926 if (counts)
927 return;
928
[d7baee6]929 for (i = 0; i < MAX_ANIMATIONS; i++) {
[00bb6965]930 if (!animations[i].animlen || !animations[i].initialized ||
[b74959bd]931 !animations[i].enabled)
[1fd7700]932 continue;
[00bb6965]933 draw_pixmap(animations[i].vp,
[b74959bd]934 animations[i].pixmaps[animations[i].pos]);
[00bb6965]935 animations[i].pos = (animations[i].pos + 1) %
[b74959bd]936 animations[i].animlen;
[1fd7700]937 }
938}
939
[2ce520c]940
941static int pointer_x, pointer_y;
[a3d2939]942static int pointer_shown, pointer_enabled;
[2ce520c]943static int pointer_vport = -1;
944static int pointer_pixmap = -1;
945
[d7baee6]946static void
947mouse_show(void)
[2ce520c]948{
[d7baee6]949 int i, j;
[2ce520c]950 int visibility;
951 int color;
952 int bytepos;
953
[a3d2939]954 if (pointer_shown || !pointer_enabled)
955 return;
956
[2ce520c]957 /* Save image under the cursor */
958 if (pointer_vport == -1) {
[00bb6965]959 pointer_vport = viewport_create(pointer_x, pointer_y,
[b74959bd]960 pointer_width, pointer_height);
[2ce520c]961 if (pointer_vport < 0)
962 return;
963 } else {
964 viewports[pointer_vport].x = pointer_x;
965 viewports[pointer_vport].y = pointer_y;
966 }
967
968 if (pointer_pixmap == -1)
969 pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
970 else
[00bb6965]971 copy_vp_to_pixmap(&viewports[pointer_vport],
[b74959bd]972 &pixmaps[pointer_pixmap]);
[2ce520c]973
974 /* Draw cursor */
[00bb6965]975 for (i = 0; i < pointer_height; i++)
976 for (j = 0; j < pointer_width; j++) {
977 bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8;
[d7baee6]978 visibility = pointer_mask_bits[bytepos] &
[b74959bd]979 (1 << (j % 8));
[2ce520c]980 if (visibility) {
[b74959bd]981 color = pointer_bits[bytepos] &
982 (1 << (j % 8)) ? 0 : 0xffffff;
[00bb6965]983 if (pointer_x + j < screen.xres && pointer_y +
[b74959bd]984 i < screen.yres)
[00bb6965]985 putpixel(&viewports[0], pointer_x + j,
[b74959bd]986 pointer_y + i, color);
[2ce520c]987 }
988 }
989 pointer_shown = 1;
990}
991
[d7baee6]992static void
993mouse_hide(void)
[2ce520c]994{
995 /* Restore image under the cursor */
996 if (pointer_shown) {
997 draw_pixmap(pointer_vport, pointer_pixmap);
998 pointer_shown = 0;
999 }
1000}
1001
[d7baee6]1002static void
1003mouse_move(unsigned int x, unsigned int y)
[2ce520c]1004{
1005 mouse_hide();
1006 pointer_x = x;
1007 pointer_y = y;
1008 mouse_show();
1009}
1010
[d7baee6]1011static int
1012anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
[1fd7700]1013{
1014 int handled = 1;
1015 int retval = 0;
1016 int i,nvp;
1017 int newval;
1018
1019 switch (IPC_GET_METHOD(*call)) {
1020 case FB_ANIM_CREATE:
1021 nvp = IPC_GET_ARG1(*call);
1022 if (nvp == -1)
1023 nvp = vp;
[00bb6965]1024 if (nvp >= MAX_VIEWPORTS || nvp < 0 ||
1025 !viewports[nvp].initialized) {
[1fd7700]1026 retval = EINVAL;
1027 break;
1028 }
[00bb6965]1029 for (i = 0; i < MAX_ANIMATIONS; i++) {
1030 if (!animations[i].initialized)
[1fd7700]1031 break;
1032 }
1033 if (i == MAX_ANIMATIONS) {
1034 retval = ELIMIT;
1035 break;
1036 }
1037 animations[i].initialized = 1;
1038 animations[i].animlen = 0;
1039 animations[i].pos = 0;
1040 animations[i].enabled = 0;
1041 animations[i].vp = nvp;
1042 retval = i;
1043 break;
1044 case FB_ANIM_DROP:
1045 i = IPC_GET_ARG1(*call);
[153a209]1046 if (i >= MAX_ANIMATIONS || i < 0) {
[1fd7700]1047 retval = EINVAL;
1048 break;
1049 }
1050 animations[i].initialized = 0;
1051 break;
1052 case FB_ANIM_ADDPIXMAP:
1053 i = IPC_GET_ARG1(*call);
[00bb6965]1054 if (i >= MAX_ANIMATIONS || i < 0 ||
1055 !animations[i].initialized) {
[1fd7700]1056 retval = EINVAL;
1057 break;
1058 }
1059 if (animations[i].animlen == MAX_ANIM_LEN) {
1060 retval = ELIMIT;
1061 break;
1062 }
1063 newval = IPC_GET_ARG2(*call);
[00bb6965]1064 if (newval < 0 || newval > MAX_PIXMAPS ||
1065 !pixmaps[newval].data) {
[1fd7700]1066 retval = EINVAL;
1067 break;
1068 }
1069 animations[i].pixmaps[animations[i].animlen++] = newval;
1070 break;
1071 case FB_ANIM_CHGVP:
1072 i = IPC_GET_ARG1(*call);
1073 if (i >= MAX_ANIMATIONS || i < 0) {
1074 retval = EINVAL;
1075 break;
1076 }
1077 nvp = IPC_GET_ARG2(*call);
1078 if (nvp == -1)
1079 nvp = vp;
[00bb6965]1080 if (nvp >= MAX_VIEWPORTS || nvp < 0 ||
1081 !viewports[nvp].initialized) {
[1fd7700]1082 retval = EINVAL;
1083 break;
1084 }
1085 animations[i].vp = nvp;
1086 break;
1087 case FB_ANIM_START:
1088 case FB_ANIM_STOP:
1089 i = IPC_GET_ARG1(*call);
1090 if (i >= MAX_ANIMATIONS || i < 0) {
1091 retval = EINVAL;
1092 break;
1093 }
1094 newval = (IPC_GET_METHOD(*call) == FB_ANIM_START);
1095 if (newval ^ animations[i].enabled) {
1096 animations[i].enabled = newval;
1097 anims_enabled += newval ? 1 : -1;
1098 }
1099 break;
1100 default:
1101 handled = 0;
1102 }
1103 if (handled)
[b74959bd]1104 ipc_answer_0(callid, retval);
[1fd7700]1105 return handled;
1106}
1107
[429acb9]1108/** Handler for messages concerning pixmap handling */
[d7baee6]1109static int
1110pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
[429acb9]1111{
1112 int handled = 1;
1113 int retval = 0;
1114 int i,nvp;
1115
1116 switch (IPC_GET_METHOD(*call)) {
1117 case FB_VP_DRAW_PIXMAP:
1118 nvp = IPC_GET_ARG1(*call);
1119 if (nvp == -1)
1120 nvp = vp;
[00bb6965]1121 if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
1122 !viewports[nvp].initialized) {
[429acb9]1123 retval = EINVAL;
1124 break;
1125 }
1126 i = IPC_GET_ARG2(*call);
1127 retval = draw_pixmap(nvp, i);
1128 break;
1129 case FB_VP2PIXMAP:
1130 nvp = IPC_GET_ARG1(*call);
1131 if (nvp == -1)
1132 nvp = vp;
[00bb6965]1133 if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
1134 !viewports[nvp].initialized)
[429acb9]1135 retval = EINVAL;
1136 else
[2ce520c]1137 retval = save_vp_to_pixmap(&viewports[nvp]);
[429acb9]1138 break;
1139 case FB_DROP_PIXMAP:
1140 i = IPC_GET_ARG1(*call);
1141 if (i >= MAX_PIXMAPS) {
1142 retval = EINVAL;
1143 break;
1144 }
1145 if (pixmaps[i].data) {
1146 free(pixmaps[i].data);
1147 pixmaps[i].data = NULL;
1148 }
1149 break;
1150 default:
1151 handled = 0;
1152 }
1153
1154 if (handled)
[b74959bd]1155 ipc_answer_0(callid, retval);
[429acb9]1156 return handled;
1157
1158}
1159
[1180a88e]1160/** Function for handling connections to FB
1161 *
1162 */
[d7baee6]1163static void
1164fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
[a2ae4f4]1165{
1166 ipc_callid_t callid;
1167 ipc_call_t call;
1168 int retval;
1169 int i;
1170 unsigned int row,col;
1171 char c;
[88c3151]1172
[a2ae4f4]1173 int vp = 0;
[88c3151]1174 viewport_t *vport = &viewports[0];
[afa6e74]1175
[a2ae4f4]1176 if (client_connected) {
[b74959bd]1177 ipc_answer_0(iid, ELIMIT);
[a2ae4f4]1178 return;
1179 }
[88c3151]1180 client_connected = 1;
[b74959bd]1181 ipc_answer_0(iid, EOK); /* Accept connection */
[afa6e74]1182
[a2ae4f4]1183 while (1) {
[1fd7700]1184 if (vport->cursor_active || anims_enabled)
[d7baee6]1185 callid = async_get_call_timeout(&call, 250000);
[d3f2cad]1186 else
1187 callid = async_get_call(&call);
1188
[d552ab9]1189 mouse_hide();
[49d072e]1190 if (!callid) {
[bd02038]1191 cursor_blink(vport);
[1fd7700]1192 anims_tick();
[a3d2939]1193 mouse_show();
[49d072e]1194 continue;
1195 }
[90f5d64]1196 if (shm_handle(callid, &call, vp))
1197 continue;
[429acb9]1198 if (pixmap_handle(callid, &call, vp))
1199 continue;
[1fd7700]1200 if (anim_handle(callid, &call, vp))
1201 continue;
[90f5d64]1202
[a2ae4f4]1203 switch (IPC_GET_METHOD(call)) {
1204 case IPC_M_PHONE_HUNGUP:
1205 client_connected = 0;
1206 /* cleanup other viewports */
[00bb6965]1207 for (i = 1; i < MAX_VIEWPORTS; i++)
[88c3151]1208 vport->initialized = 0;
[a2ae4f4]1209 return; /* Exit thread */
[83b1d61]1210
[a2ae4f4]1211 case FB_PUTCHAR:
[d530237a]1212 case FB_TRANS_PUTCHAR:
[a2ae4f4]1213 c = IPC_GET_ARG1(call);
1214 row = IPC_GET_ARG2(call);
1215 col = IPC_GET_ARG3(call);
[88c3151]1216 if (row >= vport->rows || col >= vport->cols) {
[a2ae4f4]1217 retval = EINVAL;
1218 break;
1219 }
[b74959bd]1220 ipc_answer_0(callid, EOK);
[88c3151]1221
[00bb6965]1222 draw_char(vport, c, row, col, vport->style,
[b74959bd]1223 IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR);
[a2ae4f4]1224 continue; /* msg already answered */
1225 case FB_CLEAR:
[bd02038]1226 clear_port(vport);
1227 cursor_print(vport);
[a2ae4f4]1228 retval = 0;
1229 break;
[88c3151]1230 case FB_CURSOR_GOTO:
1231 row = IPC_GET_ARG1(call);
1232 col = IPC_GET_ARG2(call);
1233 if (row >= vport->rows || col >= vport->cols) {
1234 retval = EINVAL;
1235 break;
1236 }
1237 retval = 0;
[bd02038]1238 cursor_hide(vport);
[88c3151]1239 vport->cur_col = col;
1240 vport->cur_row = row;
[bd02038]1241 cursor_print(vport);
[88c3151]1242 break;
1243 case FB_CURSOR_VISIBILITY:
[bd02038]1244 cursor_hide(vport);
[49d072e]1245 vport->cursor_active = IPC_GET_ARG1(call);
[bd02038]1246 cursor_print(vport);
[88c3151]1247 retval = 0;
1248 break;
[a2ae4f4]1249 case FB_GET_CSIZE:
[b74959bd]1250 ipc_answer_2(callid, EOK, vport->rows, vport->cols);
[88c3151]1251 continue;
1252 case FB_SCROLL:
1253 i = IPC_GET_ARG1(call);
1254 if (i > vport->rows || i < (- (int)vport->rows)) {
1255 retval = EINVAL;
1256 break;
1257 }
[bd02038]1258 cursor_hide(vport);
1259 scroll_port(vport, i*FONT_SCANLINES);
1260 cursor_print(vport);
[88c3151]1261 retval = 0;
1262 break;
[e92aabf]1263 case FB_VIEWPORT_DB:
1264 /* Enable double buffering */
1265 i = IPC_GET_ARG1(call);
1266 if (i == -1)
1267 i = vp;
1268 if (i < 0 || i >= MAX_VIEWPORTS) {
1269 retval = EINVAL;
1270 break;
1271 }
[b74959bd]1272 if (!viewports[i].initialized ) {
[e92aabf]1273 retval = EADDRNOTAVAIL;
1274 break;
1275 }
1276 viewports[i].dboffset = 0;
1277 if (IPC_GET_ARG2(call) == 1 && !viewports[i].dbdata)
[b74959bd]1278 viewports[i].dbdata =
1279 malloc(screen.pixelbytes *
1280 viewports[i].width * viewports[i].height);
[00bb6965]1281 else if (IPC_GET_ARG2(call) == 0 &&
[b74959bd]1282 viewports[i].dbdata) {
[e92aabf]1283 free(viewports[i].dbdata);
1284 viewports[i].dbdata = NULL;
1285 }
1286 retval = 0;
1287 break;
[88c3151]1288 case FB_VIEWPORT_SWITCH:
1289 i = IPC_GET_ARG1(call);
1290 if (i < 0 || i >= MAX_VIEWPORTS) {
1291 retval = EINVAL;
1292 break;
1293 }
1294 if (! viewports[i].initialized ) {
1295 retval = EADDRNOTAVAIL;
1296 break;
1297 }
[bd02038]1298 cursor_hide(vport);
[88c3151]1299 vp = i;
1300 vport = &viewports[vp];
[bd02038]1301 cursor_print(vport);
[88c3151]1302 retval = 0;
1303 break;
1304 case FB_VIEWPORT_CREATE:
1305 retval = viewport_create(IPC_GET_ARG1(call) >> 16,
[b74959bd]1306 IPC_GET_ARG1(call) & 0xffff,
1307 IPC_GET_ARG2(call) >> 16,
1308 IPC_GET_ARG2(call) & 0xffff);
[88c3151]1309 break;
1310 case FB_VIEWPORT_DELETE:
1311 i = IPC_GET_ARG1(call);
1312 if (i < 0 || i >= MAX_VIEWPORTS) {
1313 retval = EINVAL;
1314 break;
1315 }
1316 if (! viewports[i].initialized ) {
1317 retval = EADDRNOTAVAIL;
1318 break;
1319 }
1320 viewports[i].initialized = 0;
[e92aabf]1321 if (viewports[i].dbdata) {
1322 free(viewports[i].dbdata);
1323 viewports[i].dbdata = NULL;
1324 }
[88c3151]1325 retval = 0;
1326 break;
1327 case FB_SET_STYLE:
[6b5111a]1328 vport->style.fg_color = IPC_GET_ARG1(call);
1329 vport->style.bg_color = IPC_GET_ARG2(call);
[88c3151]1330 retval = 0;
1331 break;
1332 case FB_GET_RESOLUTION:
[b74959bd]1333 ipc_answer_2(callid, EOK, screen.xres, screen.yres);
[a2ae4f4]1334 continue;
[830ac99]1335 case FB_POINTER_MOVE:
[a3d2939]1336 pointer_enabled = 1;
[2ce520c]1337 mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
[153a209]1338 retval = 0;
[830ac99]1339 break;
[a2ae4f4]1340 default:
1341 retval = ENOENT;
1342 }
[b74959bd]1343 ipc_answer_0(callid, retval);
[a2ae4f4]1344 }
[afa6e74]1345}
1346
[1180a88e]1347/** Initialization of framebuffer */
[d7baee6]1348int
1349fb_init(void)
[a2ae4f4]1350{
[bf9afa07]1351 void *fb_ph_addr;
[da0c91e7]1352 unsigned int fb_width;
1353 unsigned int fb_height;
1354 unsigned int fb_scanline;
[2bc137c2]1355 unsigned int fb_visual;
1356 bool fb_invert_colors;
[bf9afa07]1357 void *fb_addr;
1358 size_t asz;
[afa6e74]1359
[da0c91e7]1360 async_set_client_connection(fb_client_connection);
1361
[775df25]1362 fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
1363 fb_width = sysinfo_value("fb.width");
1364 fb_height = sysinfo_value("fb.height");
1365 fb_scanline = sysinfo_value("fb.scanline");
[2bc137c2]1366 fb_visual = sysinfo_value("fb.visual");
[775df25]1367 fb_invert_colors = sysinfo_value("fb.invert-colors");
[a2ae4f4]1368
[2bc137c2]1369 asz = fb_scanline * fb_height;
[2057572]1370 fb_addr = as_get_mappable_page(asz);
[a2ae4f4]1371
[00bb6965]1372 physmem_map(fb_ph_addr, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >>
[b74959bd]1373 PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
[afa6e74]1374
[f8ddd17]1375 if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual,
[b74959bd]1376 fb_invert_colors))
[2bc137c2]1377 return 0;
1378
1379 return -1;
[a2ae4f4]1380}
[da0c91e7]1381
[ce5bcb4]1382/**
1383 * @}
1384 */
Note: See TracBrowser for help on using the repository browser.