Subversion Repositories HelenOS-historic

Rev

Rev 1709 | Rev 1713 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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