source: mainline/uspace/fb/fb.c@ c738d65

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

Coding style fixes.

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