source: mainline/uspace/fb/fb.c@ 22f851e

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

Add BGR 0888 visual for Ultra 60

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