Subversion Repositories HelenOS

Rev

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

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