source: mainline/fb/fb.c@ 41269bd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 41269bd was 41269bd, checked in by Ondrej Palkovsky <ondrap@…>, 20 years ago

Fixed race condition in async framework on phone disconnect.

  • Property mode set to 100644
File size: 24.8 KB
Line 
1/*
2 * Copyright (C) 2006 Jakub Vana
3 * Copyright (C) 2006 Ondrej Palkovsky
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
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ddi.h>
34#include <sysinfo.h>
35#include <align.h>
36#include <as.h>
37#include <ipc/fb.h>
38#include <ipc/ipc.h>
39#include <ipc/ns.h>
40#include <ipc/services.h>
41#include <kernel/errno.h>
42#include <async.h>
43
44#include "font-8x16.h"
45#include "fb.h"
46#include "main.h"
47#include "../console/screenbuffer.h"
48#include "ppm.h"
49
50#define DEFAULT_BGCOLOR 0xf0f0f0
51#define DEFAULT_FGCOLOR 0x0
52
53/***************************************************************/
54/* Pixel specific fuctions */
55
56typedef void (*conv2scr_fn_t)(void *, int);
57typedef int (*conv2rgb_fn_t)(void *);
58
59struct {
60 __u8 *fbaddress ;
61
62 unsigned int xres ;
63 unsigned int yres ;
64 unsigned int scanline ;
65 unsigned int pixelbytes ;
66
67 conv2scr_fn_t rgb2scr;
68 conv2rgb_fn_t scr2rgb;
69} screen;
70
71typedef struct {
72 int initialized;
73 unsigned int x, y;
74 unsigned int width, height;
75
76 /* Text support in window */
77 unsigned int rows, cols;
78 /* Style for text printing */
79 style_t style;
80 /* Auto-cursor position */
81 int cursor_active, cur_col, cur_row;
82 int cursor_shown;
83} viewport_t;
84
85#define MAX_ANIM_LEN 8
86#define MAX_ANIMATIONS 4
87typedef struct {
88 int initialized;
89 int enabled;
90 unsigned int vp;
91
92 unsigned int pos;
93 unsigned int animlen;
94 unsigned int pixmaps[MAX_ANIM_LEN];
95} animation_t;
96static animation_t animations[MAX_ANIMATIONS];
97static int anims_enabled;
98
99/** Maximum number of saved pixmaps
100 * Pixmap is a saved rectangle
101 */
102#define MAX_PIXMAPS 256
103typedef struct {
104 unsigned int width;
105 unsigned int height;
106 __u8 *data;
107} pixmap_t;
108static pixmap_t pixmaps[MAX_PIXMAPS];
109
110/* Viewport is a rectangular area on the screen */
111#define MAX_VIEWPORTS 128
112static viewport_t viewports[128];
113
114/* Allow only 1 connection */
115static int client_connected = 0;
116
117#define RED(x, bits) ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
118#define GREEN(x, bits) ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
119#define BLUE(x, bits) ((x >> (8 - bits)) & ((1 << bits) - 1))
120
121#define COL_WIDTH 8
122#define ROW_BYTES (screen.scanline * FONT_SCANLINES)
123
124#define POINTPOS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes)
125
126/* Conversion routines between different color representations */
127static void rgb_4byte(void *dst, int rgb)
128{
129 *(int *)dst = rgb;
130}
131
132static int byte4_rgb(void *src)
133{
134 return (*(int *)src) & 0xffffff;
135}
136
137static void rgb_3byte(void *dst, int rgb)
138{
139 __u8 *scr = dst;
140#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
141 scr[0] = RED(rgb, 8);
142 scr[1] = GREEN(rgb, 8);
143 scr[2] = BLUE(rgb, 8);
144#else
145 scr[2] = RED(rgb, 8);
146 scr[1] = GREEN(rgb, 8);
147 scr[0] = BLUE(rgb, 8);
148#endif
149
150
151}
152
153static int byte3_rgb(void *src)
154{
155 __u8 *scr = src;
156#if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
157 return scr[0] << 16 | scr[1] << 8 | scr[2];
158#else
159 return scr[2] << 16 | scr[1] << 8 | scr[0];
160#endif
161}
162
163/** 16-bit depth (5:6:5) */
164static void rgb_2byte(void *dst, int rgb)
165{
166 /* 5-bit, 6-bits, 5-bits */
167 *((__u16 *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 | BLUE(rgb, 5);
168}
169
170/** 16-bit depth (5:6:5) */
171static int byte2_rgb(void *src)
172{
173 int color = *(__u16 *)(src);
174 return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
175}
176
177/** Put pixel - 8-bit depth (3:2:3) */
178static void rgb_1byte(void *dst, int rgb)
179{
180 *(__u8 *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3);
181}
182
183/** Return pixel color - 8-bit depth (3:2:3) */
184static int byte1_rgb(void *src)
185{
186 int color = *(__u8 *)src;
187 return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
188}
189
190/** Put pixel into viewport
191 *
192 * @param vp Viewport identification
193 * @param x X coord relative to viewport
194 * @param y Y coord relative to viewport
195 * @param color RGB color
196 */
197static void putpixel(int vp, unsigned int x, unsigned int y, int color)
198{
199 int dx = viewports[vp].x + x;
200 int dy = viewports[vp].y + y;
201 (*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)],color);
202}
203/** Get pixel from viewport */
204static int getpixel(int vp, unsigned int x, unsigned int y)
205{
206 int dx = viewports[vp].x + x;
207 int dy = viewports[vp].y + y;
208
209 return (*screen.scr2rgb)(&screen.fbaddress[POINTPOS(dx,dy)]);
210}
211
212/** Fill line with color BGCOLOR */
213static void clear_line(int vp, unsigned int y)
214{
215 unsigned int x;
216 for (x = 0; x < viewports[vp].width; x++)
217 putpixel(vp, x, y, viewports[vp].style.bg_color);
218}
219
220static void draw_rectangle(int vp, unsigned int sx, unsigned int sy,
221 unsigned int width, unsigned int height,
222 int color)
223{
224 unsigned int x, y;
225
226 /* Clear first line */
227 for (x = 0; x < width; x++)
228 putpixel(vp, sx + x, sy, color);
229
230 /* Recompute to screen coords */
231 sx += viewports[vp].x;
232 sy += viewports[vp].y;
233 /* Copy the rest */
234 for (y = sy+1;y < sy+height; y++)
235 memcpy(&screen.fbaddress[POINTPOS(sx,y)],
236 &screen.fbaddress[POINTPOS(sx,sy)],
237 screen.pixelbytes * width);
238
239}
240
241/** Fill viewport with background color */
242static void clear_port(int vp)
243{
244 viewport_t *vport = &viewports[vp];
245
246 draw_rectangle(vp, 0, 0, vport->width, vport->height, vport->style.bg_color);
247}
248
249/** Scroll port up/down
250 *
251 * @param vp Viewport to scroll
252 * @param rows Positive number - scroll up, negative - scroll down
253 */
254static void scroll_port(int vp, int rows)
255{
256 int y;
257 int startline;
258 int endline;
259 viewport_t *vport = &viewports[vp];
260
261 if (rows > 0) {
262 for (y=vport->y; y < vport->y+vport->height - rows*FONT_SCANLINES; y++)
263 memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
264 &screen.fbaddress[POINTPOS(vport->x,y + rows*FONT_SCANLINES)],
265 screen.pixelbytes * vport->width);
266 draw_rectangle(vp, 0, FONT_SCANLINES*(vport->rows - 1),
267 vport->width, FONT_SCANLINES, vport->style.bg_color);
268 } else if (rows < 0) {
269 rows = -rows;
270 for (y=vport->y + vport->height-1; y >= vport->y + rows*FONT_SCANLINES; y--)
271 memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
272 &screen.fbaddress[POINTPOS(vport->x,y - rows*FONT_SCANLINES)],
273 screen.pixelbytes * vport->width);
274 draw_rectangle(vp, 0, 0, vport->width, FONT_SCANLINES, vport->style.bg_color);
275 }
276}
277
278static void invert_pixel(int vp,unsigned int x, unsigned int y)
279{
280 putpixel(vp, x, y, ~getpixel(vp, x, y));
281}
282
283
284/***************************************************************/
285/* Character-console functions */
286
287/** Draw character at given position
288 *
289 * @param vp Viewport where the character is printed
290 * @param sx Coordinates of top-left of the character
291 * @param sy Coordinates of top-left of the character
292 * @param style Color of the character
293 * @param transparent If false, print background color
294 */
295static void draw_glyph(int vp,__u8 glyph, unsigned int sx, unsigned int sy,
296 style_t style, int transparent)
297{
298 int i;
299 unsigned int y;
300 unsigned int glline;
301
302 for (y = 0; y < FONT_SCANLINES; y++) {
303 glline = fb_font[glyph * FONT_SCANLINES + y];
304 for (i = 0; i < 8; i++) {
305 if (glline & (1 << (7 - i)))
306 putpixel(vp, sx + i, sy + y, style.fg_color);
307 else if (!transparent)
308 putpixel(vp, sx + i, sy + y, style.bg_color);
309 }
310 }
311}
312
313/** Invert character at given position */
314static void invert_char(int vp,unsigned int row, unsigned int col)
315{
316 unsigned int x;
317 unsigned int y;
318
319 for (x = 0; x < COL_WIDTH; x++)
320 for (y = 0; y < FONT_SCANLINES; y++)
321 invert_pixel(vp, col * COL_WIDTH + x, row * FONT_SCANLINES + y);
322}
323
324/***************************************************************/
325/* Stdout specific functions */
326
327
328/** Create new viewport
329 *
330 * @return New viewport number
331 */
332static int viewport_create(unsigned int x, unsigned int y,unsigned int width,
333 unsigned int height)
334{
335 int i;
336
337 for (i=0; i < MAX_VIEWPORTS; i++) {
338 if (!viewports[i].initialized)
339 break;
340 }
341 if (i == MAX_VIEWPORTS)
342 return ELIMIT;
343
344 if (width ==0 || height == 0 ||
345 x+width > screen.xres || y+height > screen.yres)
346 return EINVAL;
347 if (width < FONT_SCANLINES || height < COL_WIDTH)
348 return EINVAL;
349
350 viewports[i].x = x;
351 viewports[i].y = y;
352 viewports[i].width = width;
353 viewports[i].height = height;
354
355 viewports[i].rows = height / FONT_SCANLINES;
356 viewports[i].cols = width / COL_WIDTH;
357
358 viewports[i].style.bg_color = DEFAULT_BGCOLOR;
359 viewports[i].style.fg_color = DEFAULT_FGCOLOR;
360
361 viewports[i].cur_col = 0;
362 viewports[i].cur_row = 0;
363 viewports[i].cursor_active = 0;
364
365 viewports[i].initialized = 1;
366
367 return i;
368}
369
370
371/** Initialize framebuffer as a chardev output device
372 *
373 * @param addr Address of theframebuffer
374 * @param x Screen width in pixels
375 * @param y Screen height in pixels
376 * @param bpp Bits per pixel (8, 16, 24, 32)
377 * @param scan Bytes per one scanline
378 *
379 */
380static void screen_init(void *addr, unsigned int xres, unsigned int yres, unsigned int bpp, unsigned int scan)
381{
382 switch (bpp) {
383 case 8:
384 screen.rgb2scr = rgb_1byte;
385 screen.scr2rgb = byte1_rgb;
386 screen.pixelbytes = 1;
387 break;
388 case 16:
389 screen.rgb2scr = rgb_2byte;
390 screen.scr2rgb = byte2_rgb;
391 screen.pixelbytes = 2;
392 break;
393 case 24:
394 screen.rgb2scr = rgb_3byte;
395 screen.scr2rgb = byte3_rgb;
396 screen.pixelbytes = 3;
397 break;
398 case 32:
399 screen.rgb2scr = rgb_4byte;
400 screen.scr2rgb = byte4_rgb;
401 screen.pixelbytes = 4;
402 break;
403 }
404
405
406 screen.fbaddress = (unsigned char *) addr;
407 screen.xres = xres;
408 screen.yres = yres;
409 screen.scanline = scan;
410
411 /* Create first viewport */
412 viewport_create(0,0,xres,yres);
413}
414
415/** Hide cursor if it is shown */
416static void cursor_hide(int vp)
417{
418 viewport_t *vport = &viewports[vp];
419
420 if (vport->cursor_active && vport->cursor_shown) {
421 invert_char(vp, vport->cur_row, vport->cur_col);
422 vport->cursor_shown = 0;
423 }
424}
425
426/** Show cursor if cursor showing is enabled */
427static void cursor_print(int vp)
428{
429 viewport_t *vport = &viewports[vp];
430
431 /* Do not check for cursor_shown */
432 if (vport->cursor_active) {
433 invert_char(vp, vport->cur_row, vport->cur_col);
434 vport->cursor_shown = 1;
435 }
436}
437
438/** Invert cursor, if it is enabled */
439static void cursor_blink(int vp)
440{
441 viewport_t *vport = &viewports[vp];
442
443 if (vport->cursor_shown)
444 cursor_hide(vp);
445 else
446 cursor_print(vp);
447}
448
449/** Draw character at given position relative to viewport
450 *
451 * @param vp Viewport identification
452 * @param c Character to print
453 * @param row Screen position relative to viewport
454 * @param col Screen position relative to viewport
455 * @param transparent If false, print background color with character
456 */
457static void draw_char(int vp, char c, unsigned int row, unsigned int col, style_t style, int transparent)
458{
459 viewport_t *vport = &viewports[vp];
460
461 /* Optimize - do not hide cursor if we are going to overwrite it */
462 if (vport->cursor_active && vport->cursor_shown &&
463 (vport->cur_col != col || vport->cur_row != row))
464 invert_char(vp, vport->cur_row, vport->cur_col);
465
466 draw_glyph(vp, c, col * COL_WIDTH, row * FONT_SCANLINES, style, transparent);
467
468 vport->cur_col = col;
469 vport->cur_row = row;
470
471 vport->cur_col++;
472 if (vport->cur_col>= vport->cols) {
473 vport->cur_col = 0;
474 vport->cur_row++;
475 if (vport->cur_row >= vport->rows)
476 vport->cur_row--;
477 }
478 cursor_print(vp);
479}
480
481/** Draw text data to viewport
482 *
483 * @param vp Viewport id
484 * @param data Text data fitting exactly into viewport
485 */
486static void draw_text_data(int vp, keyfield_t *data)
487{
488 viewport_t *vport = &viewports[vp];
489 int i;
490 char c;
491 int col,row;
492
493 clear_port(vp);
494 for (i=0; i < vport->cols * vport->rows; i++) {
495 if (data[i].character == ' ' && style_same(data[i].style,vport->style))
496 continue;
497 col = i % vport->cols;
498 row = i / vport->cols;
499 draw_glyph(vp, data[i].character, col * COL_WIDTH, row * FONT_SCANLINES,
500 data[i].style, style_same(data[i].style,vport->style));
501 }
502 cursor_print(vp);
503}
504
505
506/** Return first free pixmap */
507static int find_free_pixmap(void)
508{
509 int i;
510
511 for (i=0;i < MAX_PIXMAPS;i++)
512 if (!pixmaps[i].data)
513 return i;
514 return -1;
515}
516
517static void putpixel_pixmap(int pm, unsigned int x, unsigned int y, int color)
518{
519 pixmap_t *pmap = &pixmaps[pm];
520 int pos = (y * pmap->width + x) * screen.pixelbytes;
521
522 (*screen.rgb2scr)(&pmap->data[pos],color);
523}
524
525/** Create a new pixmap and return appropriate ID */
526static int shm2pixmap(char *shm, size_t size)
527{
528 int pm;
529 pixmap_t *pmap;
530
531 pm = find_free_pixmap();
532 if (pm == -1)
533 return ELIMIT;
534 pmap = &pixmaps[pm];
535
536 if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
537 return EINVAL;
538
539 pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
540 if (!pmap->data)
541 return ENOMEM;
542
543 ppm_draw(shm, size, 0, 0, pmap->width, pmap->height,
544 putpixel_pixmap, pm);
545
546 return pm;
547}
548
549/** Handle shared memory communication calls
550 *
551 * Protocol for drawing pixmaps:
552 * - FB_PREPARE_SHM(client shm identification)
553 * - IPC_M_SEND_AS_AREA
554 * - FB_DRAW_PPM(startx,starty)
555 * - FB_DROP_SHM
556 *
557 * Protocol for text drawing
558 * - IPC_M_SEND_AS_AREA
559 * - FB_DRAW_TEXT_DATA
560 *
561 * @param callid Callid of the current call
562 * @param call Current call data
563 * @param vp Active viewport
564 * @return 0 if the call was not handled byt this function, 1 otherwise
565 *
566 * note: this function is not threads safe, you would have
567 * to redefine static variables with __thread
568 */
569static int shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
570{
571 static keyfield_t *interbuffer = NULL;
572 static size_t intersize = 0;
573
574 static char *shm = NULL;
575 static ipcarg_t shm_id = 0;
576 static size_t shm_size;
577
578 int handled = 1;
579 int retval = 0;
580 viewport_t *vport = &viewports[vp];
581 unsigned int x,y;
582
583 switch (IPC_GET_METHOD(*call)) {
584 case IPC_M_AS_AREA_SEND:
585 /* We accept one area for data interchange */
586 if (IPC_GET_ARG1(*call) == shm_id) {
587 void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
588 shm_size = IPC_GET_ARG2(*call);
589 if (!ipc_answer_fast(callid, 0, (sysarg_t)dest, 0))
590 shm = dest;
591 else
592 shm_id = 0;
593 if (shm[0] != 'P')
594 while (1)
595 ;
596 return 1;
597 } else {
598 intersize = IPC_GET_ARG2(*call);
599 receive_comm_area(callid,call,(void **)&interbuffer);
600 }
601 return 1;
602 case FB_PREPARE_SHM:
603 if (shm_id)
604 retval = EBUSY;
605 else
606 shm_id = IPC_GET_ARG1(*call);
607 break;
608
609 case FB_DROP_SHM:
610 if (shm) {
611 as_area_destroy(shm);
612 shm = NULL;
613 }
614 shm_id = 0;
615 break;
616
617 case FB_SHM2PIXMAP:
618 if (!shm) {
619 retval = EINVAL;
620 break;
621 }
622 retval = shm2pixmap(shm, shm_size);
623 break;
624 case FB_DRAW_PPM:
625 if (!shm) {
626 retval = EINVAL;
627 break;
628 }
629 x = IPC_GET_ARG1(*call);
630 y = IPC_GET_ARG2(*call);
631 if (x > vport->width || y > vport->height) {
632 retval = EINVAL;
633 break;
634 }
635
636 ppm_draw(shm, shm_size, IPC_GET_ARG1(*call), IPC_GET_ARG2(*call),
637 vport->width - x, vport->height - y, putpixel, vp);
638 break;
639 case FB_DRAW_TEXT_DATA:
640 if (!interbuffer) {
641 retval = EINVAL;
642 break;
643 }
644 if (intersize < vport->cols*vport->rows*sizeof(*interbuffer)) {
645 retval = EINVAL;
646 break;
647 }
648 draw_text_data(vp, interbuffer);
649 break;
650 default:
651 handled = 0;
652 }
653
654 if (handled)
655 ipc_answer_fast(callid, retval, 0, 0);
656 return handled;
657}
658
659/** Save viewport to pixmap */
660static int save_vp_to_pixmap(int vp)
661{
662 int pm;
663 pixmap_t *pmap;
664 viewport_t *vport = &viewports[vp];
665 int x,y;
666 int rowsize;
667 int tmp;
668
669 pm = find_free_pixmap();
670 if (pm == -1)
671 return ELIMIT;
672
673 pmap = &pixmaps[pm];
674 pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
675 if (!pmap->data)
676 return ENOMEM;
677
678 pmap->width = vport->width;
679 pmap->height = vport->height;
680
681 rowsize = vport->width * screen.pixelbytes;
682 for (y=0;y < vport->height; y++) {
683 tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
684 memcpy(pmap->data + rowsize*y, screen.fbaddress + tmp, rowsize);
685 }
686 return pm;
687}
688
689/** Draw pixmap on screen
690 *
691 * @param vp Viewport to draw on
692 * @param pm Pixmap identifier
693 */
694static int draw_pixmap(int vp, int pm)
695{
696 pixmap_t *pmap = &pixmaps[pm];
697 viewport_t *vport = &viewports[vp];
698 int x,y;
699 int tmp, srcrowsize;
700 int realwidth, realheight, realrowsize;
701
702 if (!pmap->data)
703 return EINVAL;
704
705 realwidth = pmap->width <= vport->width ? pmap->width : vport->width;
706 realheight = pmap->height <= vport->height ? pmap->height : vport->height;
707
708 srcrowsize = vport->width * screen.pixelbytes;
709 realrowsize = realwidth * screen.pixelbytes;
710
711 for (y=0; y < realheight; y++) {
712 tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
713 memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize, realrowsize);
714 }
715 return 0;
716}
717
718/** Tick animation one step forward */
719static void anims_tick(void)
720{
721 int i;
722 static int counts = 0;
723
724 /* Limit redrawing */
725 counts = (counts+1) % 8;
726 if (counts)
727 return;
728
729 for (i=0; i < MAX_ANIMATIONS; i++) {
730 if (!animations[i].animlen || !animations[i].initialized || !animations[i].enabled)
731 continue;
732 draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
733 animations[i].pos = (animations[i].pos+1) % animations[i].animlen;
734 }
735}
736
737static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
738{
739 int handled = 1;
740 int retval = 0;
741 int i,nvp;
742 int newval;
743
744 switch (IPC_GET_METHOD(*call)) {
745 case FB_ANIM_CREATE:
746 nvp = IPC_GET_ARG1(*call);
747 if (nvp == -1)
748 nvp = vp;
749 if (nvp >= MAX_VIEWPORTS || nvp < 0 || !viewports[nvp].initialized) {
750 retval = EINVAL;
751 break;
752 }
753 for (i=0; i < MAX_ANIMATIONS; i++) {
754 if (! animations[i].initialized)
755 break;
756 }
757 if (i == MAX_ANIMATIONS) {
758 retval = ELIMIT;
759 break;
760 }
761 animations[i].initialized = 1;
762 animations[i].animlen = 0;
763 animations[i].pos = 0;
764 animations[i].enabled = 0;
765 animations[i].vp = nvp;
766 retval = i;
767 break;
768 case FB_ANIM_DROP:
769 i = IPC_GET_ARG1(*call);
770 if (nvp >= MAX_ANIMATIONS || i < 0) {
771 retval = EINVAL;
772 break;
773 }
774 animations[i].initialized = 0;
775 break;
776 case FB_ANIM_ADDPIXMAP:
777 i = IPC_GET_ARG1(*call);
778 if (i >= MAX_ANIMATIONS || i < 0 || !animations[i].initialized) {
779 retval = EINVAL;
780 break;
781 }
782 if (animations[i].animlen == MAX_ANIM_LEN) {
783 retval = ELIMIT;
784 break;
785 }
786 newval = IPC_GET_ARG2(*call);
787 if (newval < 0 || newval > MAX_PIXMAPS || !pixmaps[newval].data) {
788 retval = EINVAL;
789 break;
790 }
791 animations[i].pixmaps[animations[i].animlen++] = newval;
792 break;
793 case FB_ANIM_CHGVP:
794 i = IPC_GET_ARG1(*call);
795 if (i >= MAX_ANIMATIONS || i < 0) {
796 retval = EINVAL;
797 break;
798 }
799 nvp = IPC_GET_ARG2(*call);
800 if (nvp == -1)
801 nvp = vp;
802 if (nvp >= MAX_VIEWPORTS || nvp < 0 || !viewports[nvp].initialized) {
803 retval = EINVAL;
804 break;
805 }
806 animations[i].vp = nvp;
807 break;
808 case FB_ANIM_START:
809 case FB_ANIM_STOP:
810 i = IPC_GET_ARG1(*call);
811 if (i >= MAX_ANIMATIONS || i < 0) {
812 retval = EINVAL;
813 break;
814 }
815 newval = (IPC_GET_METHOD(*call) == FB_ANIM_START);
816 if (newval ^ animations[i].enabled) {
817 animations[i].enabled = newval;
818 anims_enabled += newval ? 1 : -1;
819 }
820 break;
821 default:
822 handled = 0;
823 }
824 if (handled)
825 ipc_answer_fast(callid, retval, 0, 0);
826 return handled;
827}
828
829/** Handler for messages concerning pixmap handling */
830static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
831{
832 int handled = 1;
833 int retval = 0;
834 int i,nvp;
835
836 switch (IPC_GET_METHOD(*call)) {
837 case FB_VP_DRAW_PIXMAP:
838 nvp = IPC_GET_ARG1(*call);
839 if (nvp == -1)
840 nvp = vp;
841 if (nvp < 0 || nvp >= MAX_VIEWPORTS || !viewports[nvp].initialized) {
842 retval = EINVAL;
843 break;
844 }
845 i = IPC_GET_ARG2(*call);
846 retval = draw_pixmap(nvp, i);
847 break;
848 case FB_VP2PIXMAP:
849 nvp = IPC_GET_ARG1(*call);
850 if (nvp == -1)
851 nvp = vp;
852 if (nvp < 0 || nvp >= MAX_VIEWPORTS || !viewports[nvp].initialized)
853 retval = EINVAL;
854 else
855 retval = save_vp_to_pixmap(nvp);
856 break;
857 case FB_DROP_PIXMAP:
858 i = IPC_GET_ARG1(*call);
859 if (i >= MAX_PIXMAPS) {
860 retval = EINVAL;
861 break;
862 }
863 if (pixmaps[i].data) {
864 free(pixmaps[i].data);
865 pixmaps[i].data = NULL;
866 }
867 break;
868 default:
869 handled = 0;
870 }
871
872 if (handled)
873 ipc_answer_fast(callid, retval, 0, 0);
874 return handled;
875
876}
877
878/** Function for handling connections to FB
879 *
880 */
881static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
882{
883 ipc_callid_t callid;
884 ipc_call_t call;
885 int retval;
886 int i;
887 unsigned int row,col;
888 char c;
889
890 int vp = 0;
891 viewport_t *vport = &viewports[0];
892
893 if (client_connected) {
894 ipc_answer_fast(iid, ELIMIT, 0,0);
895 return;
896 }
897 client_connected = 1;
898 ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
899
900 while (1) {
901 if (vport->cursor_active || anims_enabled)
902 callid = async_get_call_timeout(&call,250000);
903 else
904 callid = async_get_call(&call);
905
906 if (!callid) {
907 cursor_blink(vp);
908 anims_tick();
909 continue;
910 }
911 if (shm_handle(callid, &call, vp))
912 continue;
913 if (pixmap_handle(callid, &call, vp))
914 continue;
915 if (anim_handle(callid, &call, vp))
916 continue;
917
918 switch (IPC_GET_METHOD(call)) {
919 case IPC_M_PHONE_HUNGUP:
920 client_connected = 0;
921 /* cleanup other viewports */
922 for (i=1; i < MAX_VIEWPORTS; i++)
923 vport->initialized = 0;
924 return; /* Exit thread */
925
926 case FB_PUTCHAR:
927 case FB_TRANS_PUTCHAR:
928 c = IPC_GET_ARG1(call);
929 row = IPC_GET_ARG2(call);
930 col = IPC_GET_ARG3(call);
931 if (row >= vport->rows || col >= vport->cols) {
932 retval = EINVAL;
933 break;
934 }
935 ipc_answer_fast(callid,0,0,0);
936
937 draw_char(vp, c, row, col, vport->style, IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR);
938 continue; /* msg already answered */
939 case FB_CLEAR:
940 clear_port(vp);
941 cursor_print(vp);
942 retval = 0;
943 break;
944 case FB_CURSOR_GOTO:
945 row = IPC_GET_ARG1(call);
946 col = IPC_GET_ARG2(call);
947 if (row >= vport->rows || col >= vport->cols) {
948 retval = EINVAL;
949 break;
950 }
951 retval = 0;
952 cursor_hide(vp);
953 vport->cur_col = col;
954 vport->cur_row = row;
955 cursor_print(vp);
956 break;
957 case FB_CURSOR_VISIBILITY:
958 cursor_hide(vp);
959 vport->cursor_active = IPC_GET_ARG1(call);
960 cursor_print(vp);
961 retval = 0;
962 break;
963 case FB_GET_CSIZE:
964 ipc_answer_fast(callid, 0, vport->rows, vport->cols);
965 continue;
966 case FB_SCROLL:
967 i = IPC_GET_ARG1(call);
968 if (i > vport->rows || i < (- (int)vport->rows)) {
969 retval = EINVAL;
970 break;
971 }
972 cursor_hide(vp);
973 scroll_port(vp, i);
974 cursor_print(vp);
975 retval = 0;
976 break;
977 case FB_VIEWPORT_SWITCH:
978 i = IPC_GET_ARG1(call);
979 if (i < 0 || i >= MAX_VIEWPORTS) {
980 retval = EINVAL;
981 break;
982 }
983 if (! viewports[i].initialized ) {
984 retval = EADDRNOTAVAIL;
985 break;
986 }
987 cursor_hide(vp);
988 vp = i;
989 vport = &viewports[vp];
990 cursor_print(vp);
991 retval = 0;
992 break;
993 case FB_VIEWPORT_CREATE:
994 retval = viewport_create(IPC_GET_ARG1(call) >> 16,
995 IPC_GET_ARG1(call) & 0xffff,
996 IPC_GET_ARG2(call) >> 16,
997 IPC_GET_ARG2(call) & 0xffff);
998 break;
999 case FB_VIEWPORT_DELETE:
1000 i = IPC_GET_ARG1(call);
1001 if (i < 0 || i >= MAX_VIEWPORTS) {
1002 retval = EINVAL;
1003 break;
1004 }
1005 if (! viewports[i].initialized ) {
1006 retval = EADDRNOTAVAIL;
1007 break;
1008 }
1009 viewports[i].initialized = 0;
1010 retval = 0;
1011 break;
1012 case FB_SET_STYLE:
1013 vport->style.fg_color = IPC_GET_ARG1(call);
1014 vport->style.bg_color = IPC_GET_ARG2(call);
1015 retval = 0;
1016 break;
1017 case FB_GET_RESOLUTION:
1018 ipc_answer_fast(callid, 0, screen.xres,screen.yres);
1019 continue;
1020 default:
1021 retval = ENOENT;
1022 }
1023 ipc_answer_fast(callid,retval,0,0);
1024 }
1025}
1026
1027/** Initialization of framebuffer */
1028int fb_init(void)
1029{
1030 void *fb_ph_addr;
1031 unsigned int fb_width;
1032 unsigned int fb_height;
1033 unsigned int fb_bpp;
1034 unsigned int fb_scanline;
1035 void *fb_addr;
1036 size_t asz;
1037
1038 async_set_client_connection(fb_client_connection);
1039
1040 fb_ph_addr=(void *)sysinfo_value("fb.address.physical");
1041 fb_width=sysinfo_value("fb.width");
1042 fb_height=sysinfo_value("fb.height");
1043 fb_bpp=sysinfo_value("fb.bpp");
1044 fb_scanline=sysinfo_value("fb.scanline");
1045
1046 asz = fb_scanline*fb_height;
1047 fb_addr = as_get_mappable_page(asz);
1048
1049 map_physmem(fb_ph_addr, fb_addr, ALIGN_UP(asz,PAGE_SIZE) >>PAGE_WIDTH,
1050 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
1051
1052 screen_init(fb_addr, fb_width, fb_height, fb_bpp, fb_scanline);
1053
1054 return 0;
1055}
1056
Note: See TracBrowser for help on using the repository browser.