Subversion Repositories HelenOS-historic

Rev

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

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