Subversion Repositories HelenOS

Rev

Rev 3684 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3684 Rev 4377
Line 1... Line 1...
1
/*
1
/*
-
 
2
 * Copyright (c) 2008 Martin Decky
2
 * Copyright (c) 2006 Jakub Vana
3
 * Copyright (c) 2006 Jakub Vana
3
 * Copyright (c) 2006 Ondrej Palkovsky
4
 * Copyright (c) 2006 Ondrej Palkovsky
4
 * All rights reserved.
5
 * All rights reserved.
5
 *
6
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
Line 27... Line 28...
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
 */
29
 
30
 
30
/**
31
/**
31
 * @defgroup fb Graphical framebuffer
32
 * @defgroup fb Graphical framebuffer
32
 * @brief   HelenOS graphical framebuffer.
33
 * @brief HelenOS graphical framebuffer.
33
 * @ingroup fbs
34
 * @ingroup fbs
34
 * @{
35
 * @{
35
 */
36
 */
36
 
37
 
37
/** @file
38
/** @file
38
 */
39
 */
39
 
40
 
40
#include <stdlib.h>
41
#include <stdlib.h>
Line 48... Line 49...
48
#include <ipc/ipc.h>
49
#include <ipc/ipc.h>
49
#include <ipc/ns.h>
50
#include <ipc/ns.h>
50
#include <ipc/services.h>
51
#include <ipc/services.h>
51
#include <kernel/errno.h>
52
#include <kernel/errno.h>
52
#include <kernel/genarch/fb/visuals.h>
53
#include <kernel/genarch/fb/visuals.h>
-
 
54
#include <console/color.h>
-
 
55
#include <console/style.h>
53
#include <async.h>
56
#include <async.h>
54
#include <bool.h>
57
#include <bool.h>
55
 
58
 
56
#include "font-8x16.h"
59
#include "font-8x16.h"
57
#include "fb.h"
60
#include "fb.h"
Line 60... Line 63...
60
#include "ppm.h"
63
#include "ppm.h"
61
 
64
 
62
#include "pointer.xbm"
65
#include "pointer.xbm"
63
#include "pointer_mask.xbm"
66
#include "pointer_mask.xbm"
64
 
67
 
65
#define DEFAULT_BGCOLOR                0xf0f0f0
68
#define DEFAULT_BGCOLOR  0xf0f0f0
66
#define DEFAULT_FGCOLOR                0x0
69
#define DEFAULT_FGCOLOR  0x000000
67
 
70
 
68
/***************************************************************/
-
 
69
/* Pixel specific fuctions */
71
#define GLYPH_UNAVAIL    '?'
70
 
72
 
71
typedef void (*conv2scr_fn_t)(void *, int);
73
#define MAX_ANIM_LEN     8
72
typedef int (*conv2rgb_fn_t)(void *);
74
#define MAX_ANIMATIONS   4
-
 
75
#define MAX_PIXMAPS      256  /**< Maximum number of saved pixmaps */
-
 
76
#define MAX_VIEWPORTS    128  /**< Viewport is a rectangular area on the screen */
73
 
77
 
-
 
78
/** Function to render a pixel from a RGB value. */
-
 
79
typedef void (*rgb_conv_t)(void *, uint32_t);
-
 
80
 
-
 
81
/** Function to render a bit mask. */
-
 
82
typedef void (*mask_conv_t)(void *, bool);
74
struct {
83
 
75
    uint8_t *fbaddress;
84
/** Function to draw a glyph. */
-
 
85
typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor,
-
 
86
    uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
76
 
87
 
-
 
88
struct {
-
 
89
    uint8_t *fb_addr;
-
 
90
   
77
    unsigned int xres;
91
    unsigned int xres;
78
    unsigned int yres;
92
    unsigned int yres;
-
 
93
   
79
    unsigned int scanline;
94
    unsigned int scanline;
-
 
95
    unsigned int glyphscanline;
-
 
96
   
80
    unsigned int pixelbytes;
97
    unsigned int pixelbytes;
81
    unsigned int invert_colors;
98
    unsigned int glyphbytes;
82
 
99
   
-
 
100
    /** Pre-rendered mask for rendering glyphs. Specific for the visual. */
-
 
101
    uint8_t *glyphs;
-
 
102
   
83
    conv2scr_fn_t rgb2scr;
103
    rgb_conv_t rgb_conv;
84
    conv2rgb_fn_t scr2rgb;
104
    mask_conv_t mask_conv;
85
} screen;
105
} screen;
86
 
106
 
-
 
107
/** Backbuffer character cell. */
87
typedef struct {
108
typedef struct {
88
    int initialized;
109
    uint32_t glyph;
89
    unsigned int x, y;
110
    uint32_t fg_color;
90
    unsigned int width, height;
111
    uint32_t bg_color;
-
 
112
} bb_cell_t;
91
 
113
 
-
 
114
typedef struct {
-
 
115
    bool initialized;
-
 
116
    unsigned int x;
-
 
117
    unsigned int y;
-
 
118
    unsigned int width;
-
 
119
    unsigned int height;
-
 
120
   
92
    /* Text support in window */
121
    /* Text support in window */
-
 
122
    unsigned int cols;
93
    unsigned int rows, cols;
123
    unsigned int rows;
-
 
124
   
-
 
125
    /*
94
    /* Style for text printing */
126
     * Style and glyphs for text printing
-
 
127
     */
-
 
128
   
-
 
129
    /** Current attributes. */
95
    style_t style;
130
    attr_rgb_t attr;
-
 
131
   
-
 
132
    uint8_t *bgpixel;
-
 
133
   
-
 
134
    /**
-
 
135
     * Glyph drawing function for this viewport.  Different viewports
-
 
136
     * might use different drawing functions depending on whether their
-
 
137
     * scanlines are aligned on a word boundary.
-
 
138
     */
-
 
139
    dg_t dglyph;
-
 
140
   
96
    /* Auto-cursor position */
141
    /* Auto-cursor position */
97
    int cursor_active, cur_col, cur_row;
142
    bool cursor_active;
-
 
143
    unsigned int cur_col;
-
 
144
    unsigned int cur_row;
98
    int cursor_shown;
145
    bool cursor_shown;
-
 
146
   
99
    /* Double buffering */
147
    /* Back buffer */
100
    uint8_t *dbdata;
148
    bb_cell_t *backbuf;
101
    unsigned int dboffset;
149
    unsigned int bbsize;
102
    unsigned int paused;
-
 
103
} viewport_t;
150
} viewport_t;
104
 
151
 
105
#define MAX_ANIM_LEN    8
-
 
106
#define MAX_ANIMATIONS  4
-
 
107
typedef struct {
152
typedef struct {
108
    int initialized;
153
    bool initialized;
109
    int enabled;
154
    bool enabled;
110
    unsigned int vp;
155
    unsigned int vp;
111
 
156
   
112
    unsigned int pos;
157
    unsigned int pos;
113
    unsigned int animlen;
158
    unsigned int animlen;
114
    unsigned int pixmaps[MAX_ANIM_LEN];
159
    unsigned int pixmaps[MAX_ANIM_LEN];
115
} animation_t;
160
} animation_t;
-
 
161
 
116
static animation_t animations[MAX_ANIMATIONS];
162
static animation_t animations[MAX_ANIMATIONS];
117
static int anims_enabled;
163
static bool anims_enabled;
118
 
164
 
119
/** Maximum number of saved pixmaps
-
 
120
 * Pixmap is a saved rectangle
-
 
121
 */
-
 
122
#define MAX_PIXMAPS        256
-
 
123
typedef struct {
165
typedef struct {
124
    unsigned int width;
166
    unsigned int width;
125
    unsigned int height;
167
    unsigned int height;
126
    uint8_t *data;
168
    uint8_t *data;
127
} pixmap_t;
169
} pixmap_t;
128
static pixmap_t pixmaps[MAX_PIXMAPS];
-
 
129
 
170
 
130
/* Viewport is a rectangular area on the screen */
171
static pixmap_t pixmaps[MAX_PIXMAPS];
131
#define MAX_VIEWPORTS 128
-
 
132
static viewport_t viewports[128];
172
static viewport_t viewports[128];
133
 
173
 
134
/* Allow only 1 connection */
-
 
135
static int client_connected = 0;
174
static bool client_connected = false;  /**< Allow only 1 connection */
136
 
175
 
-
 
176
static uint32_t color_table[16] = {
-
 
177
    [COLOR_BLACK]       = 0x000000,
137
#define RED(x, bits)    ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
178
    [COLOR_BLUE]        = 0x0000f0,
138
#define GREEN(x, bits)  ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
179
    [COLOR_GREEN]       = 0x00f000,
-
 
180
    [COLOR_CYAN]        = 0x00f0f0,
139
#define BLUE(x, bits)   ((x >> (8 - bits)) & ((1 << bits) - 1))
181
    [COLOR_RED]         = 0xf00000,
-
 
182
    [COLOR_MAGENTA]     = 0xf000f0,
-
 
183
    [COLOR_YELLOW]      = 0xf0f000,
-
 
184
    [COLOR_WHITE]       = 0xf0f0f0,
-
 
185
   
-
 
186
    [8 + COLOR_BLACK]   = 0x000000,
-
 
187
    [8 + COLOR_BLUE]    = 0x0000ff,
-
 
188
    [8 + COLOR_GREEN]   = 0x00ff00,
-
 
189
    [8 + COLOR_CYAN]    = 0x00ffff,
-
 
190
    [8 + COLOR_RED]     = 0xff0000,
-
 
191
    [8 + COLOR_MAGENTA] = 0xff00ff,
-
 
192
    [8 + COLOR_YELLOW]  = 0xffff00,
-
 
193
    [8 + COLOR_WHITE]   = 0xffffff,
-
 
194
};
140
 
195
 
-
 
196
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a);
141
#define COL_WIDTH   8
197
static int rgb_from_style(attr_rgb_t *rgb, int style);
142
#define ROW_BYTES   (screen.scanline * FONT_SCANLINES)
198
static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color,
-
 
199
    ipcarg_t bg_color, ipcarg_t flags);
143
 
200
 
144
#define POINTPOS(x, y)  ((y) * screen.scanline + (x) * screen.pixelbytes)
201
static int fb_set_color(viewport_t *vport, ipcarg_t fg_color,
-
 
202
    ipcarg_t bg_color, ipcarg_t attr);
145
 
203
 
146
static inline int COLOR(int color)
204
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
147
{
-
 
148
    return screen.invert_colors ? ~color : color;
205
    uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
149
}
-
 
-
 
206
static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,
-
 
207
    uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color);
150
 
208
 
151
/* Conversion routines between different color representations */
209
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
152
static void
-
 
153
rgb_byte0888(void *dst, int rgb)
-
 
154
{
-
 
155
    *(int *)dst = rgb;
210
    unsigned int row);
156
}
-
 
157
 
211
 
158
static int
-
 
159
byte0888_rgb(void *src)
-
 
160
{
-
 
161
    return (*(int *)src) & 0xffffff;
-
 
162
}
-
 
163
 
212
 
164
static void
-
 
165
bgr_byte0888(void *dst, int rgb)
213
#define RED(x, bits)                 ((x >> (8 + 8 + 8 - bits)) & ((1 << bits) - 1))
166
{
-
 
167
    *((uint32_t *) dst) = BLUE(rgb, 8) << 16 | GREEN(rgb, 8) << 8 |
214
#define GREEN(x, bits)               ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
168
        RED(rgb, 8);
215
#define BLUE(x, bits)                ((x >> (8 - bits)) & ((1 << bits) - 1))
169
}
-
 
170
 
216
 
171
static int
-
 
172
byte0888_bgr(void *src)
-
 
173
{
-
 
174
    int color = *(uint32_t *)(src);
217
#define COL2X(col)                   ((col) * FONT_WIDTH)
175
    return ((color & 0xff) << 16) | (((color >> 8) & 0xff) << 8) |
218
#define ROW2Y(row)                   ((row) * FONT_SCANLINES)
176
        ((color >> 16) & 0xff);
-
 
177
}
-
 
178
 
219
 
179
static void
-
 
180
rgb_byte888(void *dst, int rgb)
220
#define X2COL(x)                     ((x) / FONT_WIDTH)
181
{
-
 
182
    uint8_t *scr = dst;
-
 
183
#if defined(FB_INVERT_ENDIAN)
221
#define Y2ROW(y)                     ((y) / FONT_SCANLINES)
184
    scr[0] = RED(rgb, 8);
-
 
185
    scr[1] = GREEN(rgb, 8);
-
 
186
    scr[2] = BLUE(rgb, 8);
-
 
187
#else
-
 
188
    scr[2] = RED(rgb, 8);
-
 
189
    scr[1] = GREEN(rgb, 8);
-
 
190
    scr[0] = BLUE(rgb, 8);
-
 
191
#endif
-
 
192
}
-
 
193
 
222
 
194
static int
-
 
195
byte888_rgb(void *src)
-
 
196
{
-
 
197
    uint8_t *scr = src;
-
 
198
#if defined(FB_INVERT_ENDIAN)
223
#define FB_POS(x, y)                 ((y) * screen.scanline + (x) * screen.pixelbytes)
199
    return scr[0] << 16 | scr[1] << 8 | scr[2];
224
#define BB_POS(vport, col, row)      ((row) * vport->cols + (col))
200
#else
-
 
201
    return scr[2] << 16 | scr[1] << 8 | scr[0];
225
#define GLYPH_POS(glyph, y, cursor)  (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline)
202
#endif  
-
 
203
}
-
 
204
 
226
 
205
/**  16-bit depth (5:5:5) */
-
 
206
static void
-
 
207
rgb_byte555(void *dst, int rgb)
-
 
208
{
-
 
209
    /* 5-bit, 5-bits, 5-bits */
-
 
210
    *((uint16_t *)(dst)) = RED(rgb, 5) << 10 | GREEN(rgb, 5) << 5 |
-
 
211
        BLUE(rgb, 5);
-
 
212
}
-
 
213
 
227
 
214
/** 16-bit depth (5:5:5) */
228
/** ARGB 8:8:8:8 conversion
-
 
229
 *
215
static int
230
 */
216
byte555_rgb(void *src)
231
static void rgb_0888(void *dst, uint32_t rgb)
217
{
232
{
218
    int color = *(uint16_t *)(src);
-
 
219
    return (((color >> 10) & 0x1f) << (16 + 3)) |
233
    *((uint32_t *) dst) = rgb & 0x00ffffff;
220
        (((color >> 5) & 0x1f) << (8 + 3)) | ((color & 0x1f) << 3);
-
 
221
}
234
}
222
 
235
 
223
/**  16-bit depth (5:6:5) */
-
 
224
static void
-
 
225
rgb_byte565(void *dst, int rgb)
236
static void mask_0888(void *dst, bool mask)
226
{
237
{
227
    /* 5-bit, 6-bits, 5-bits */
-
 
228
    *((uint16_t *)(dst)) = RED(rgb, 5) << 11 | GREEN(rgb, 6) << 5 |
238
    *((uint32_t *) dst) = (mask ? 0x00ffffff : 0);
229
        BLUE(rgb, 5);
-
 
230
}
239
}
231
 
240
 
-
 
241
 
232
/** 16-bit depth (5:6:5) */
242
/** ABGR 8:8:8:8 conversion
-
 
243
 *
233
static int
244
 */
234
byte565_rgb(void *src)
245
static void bgr_0888(void *dst, uint32_t rgb)
235
{
246
{
236
    int color = *(uint16_t *)(src);
247
    *((uint32_t *) dst)
237
    return (((color >> 11) & 0x1f) << (16 + 3)) |
-
 
238
        (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
248
        = (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | RED(rgb, 8);
239
}
249
}
240
 
250
 
-
 
251
 
241
/** Put pixel - 8-bit depth (3:2:3) */
252
/** RGB 8:8:8 conversion
-
 
253
 *
242
static void
254
 */
243
rgb_byte8(void *dst, int rgb)
255
static void rgb_888(void *dst, uint32_t rgb)
244
{
256
{
-
 
257
    ((uint8_t *) dst)[0] = BLUE(rgb, 8);
245
    *(uint8_t *)dst = RED(rgb, 3) << 5 | GREEN(rgb, 2) << 3 | BLUE(rgb, 3);
258
    ((uint8_t *) dst)[1] = GREEN(rgb, 8);
-
 
259
    ((uint8_t *) dst)[2] = RED(rgb, 8);
246
}
260
}
247
 
261
 
248
/** Return pixel color - 8-bit depth (3:2:3) */
262
static void mask_888(void *dst, bool mask)
249
static int
-
 
250
byte8_rgb(void *src)
-
 
251
{
263
{
-
 
264
    if (mask) {
252
    int color = *(uint8_t *)src;
265
        ((uint8_t *) dst)[0] = 0xff;
253
    return (((color >> 5) & 0x7) << (16 + 5)) |
266
        ((uint8_t *) dst)[1] = 0xff;
254
        (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
267
        ((uint8_t *) dst)[2] = 0xff;
-
 
268
    } else {
-
 
269
        ((uint8_t *) dst)[0] = 0;
-
 
270
        ((uint8_t *) dst)[1] = 0;
-
 
271
        ((uint8_t *) dst)[2] = 0;
-
 
272
    }
255
}
273
}
256
 
274
 
-
 
275
 
257
/** Put pixel into viewport
276
/** BGR 8:8:8 conversion
258
 *
277
 *
259
 * @param vport Viewport identification
-
 
260
 * @param x X coord relative to viewport
-
 
261
 * @param y Y coord relative to viewport
-
 
262
 * @param color RGB color
-
 
263
 */
278
 */
264
static void
-
 
265
putpixel(viewport_t *vport, unsigned int x, unsigned int y, int color)
279
static void bgr_888(void *dst, uint32_t rgb)
266
{
280
{
267
    int dx = vport->x + x;
281
    ((uint8_t *) dst)[0] = RED(rgb, 8);
268
    int dy = vport->y + y;
282
    ((uint8_t *) dst)[1] = GREEN(rgb, 8);
-
 
283
    ((uint8_t *) dst)[2] = BLUE(rgb, 8);
-
 
284
}
269
 
285
 
270
    if (! (vport->paused && vport->dbdata))
-
 
271
        (*screen.rgb2scr)(&screen.fbaddress[POINTPOS(dx,dy)],
-
 
272
            COLOR(color));
-
 
273
 
286
 
274
    if (vport->dbdata) {
287
/** RGB 5:5:5 conversion
-
 
288
 *
-
 
289
 */
275
        int dline = (y + vport->dboffset) % vport->height;
290
static void rgb_555(void *dst, uint32_t rgb)
-
 
291
{
276
        int doffset = screen.pixelbytes * (dline * vport->width + x);
292
    *((uint16_t *) dst)
277
        (*screen.rgb2scr)(&vport->dbdata[doffset], COLOR(color));
293
        = (RED(rgb, 5) << 10) | (GREEN(rgb, 5) << 5) | BLUE(rgb, 5);
278
    }
-
 
279
}
294
}
280
 
295
 
281
/** Get pixel from viewport */
-
 
282
static int
-
 
283
getpixel(viewport_t *vport, unsigned int x, unsigned int y)
296
static void mask_555(void *dst, bool mask)
284
{
297
{
285
    int dx = vport->x + x;
298
    *((uint16_t *) dst) = (mask ? 0x7fff : 0);
286
    int dy = vport->y + y;
-
 
287
 
-
 
288
    return COLOR((*screen.scr2rgb)(&screen.fbaddress[POINTPOS(dx, dy)]));
-
 
289
}
299
}
290
 
300
 
-
 
301
 
291
static inline void
302
/** RGB 5:6:5 conversion
-
 
303
 *
-
 
304
 */
292
putpixel_mem(char *mem, unsigned int x, unsigned int y, int color)
305
static void rgb_565(void *dst, uint32_t rgb)
293
{
306
{
-
 
307
    *((uint16_t *) dst)
294
    (*screen.rgb2scr)(&mem[POINTPOS(x, y)], COLOR(color));
308
        = (RED(rgb, 5) << 11) | (GREEN(rgb, 6) << 5) | BLUE(rgb, 5);
295
}
309
}
296
 
310
 
297
static void
-
 
298
draw_rectangle(viewport_t *vport, unsigned int sx, unsigned int sy,
-
 
299
    unsigned int width, unsigned int height, int color)
311
static void mask_565(void *dst, bool mask)
300
{
312
{
301
    unsigned int x, y;
313
    *((uint16_t *) dst) = (mask ? 0xffff : 0);
302
    static void *tmpline;
-
 
303
 
314
}
304
    if (!tmpline)
-
 
305
        tmpline = malloc(screen.scanline * screen.pixelbytes);
-
 
306
 
315
 
307
    /* Clear first line */
-
 
308
    for (x = 0; x < width; x++)
-
 
309
        putpixel_mem(tmpline, x, 0, color);
-
 
310
 
-
 
311
    if (!vport->paused) {
-
 
312
        /* Recompute to screen coords */
-
 
313
        sx += vport->x;
-
 
314
        sy += vport->y;
-
 
315
        /* Copy the rest */
-
 
316
        for (y = sy;y < sy+height; y++)
-
 
317
            memcpy(&screen.fbaddress[POINTPOS(sx,y)], tmpline,
-
 
318
                screen.pixelbytes * width);
-
 
319
    }
-
 
320
    if (vport->dbdata) {
-
 
321
        for (y = sy; y < sy + height; y++) {
-
 
322
            int rline = (y + vport->dboffset) % vport->height;
-
 
323
            int rpos = (rline * vport->width + sx) *
-
 
324
                screen.pixelbytes;
-
 
325
            memcpy(&vport->dbdata[rpos], tmpline,
-
 
326
                screen.pixelbytes * width);
-
 
327
        }
-
 
328
    }
-
 
329
 
316
 
-
 
317
/** RGB 3:2:3
-
 
318
 *
-
 
319
 */
-
 
320
static void rgb_323(void *dst, uint32_t rgb)
-
 
321
{
-
 
322
    *((uint8_t *) dst)
-
 
323
        = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
330
}
324
}
331
 
325
 
332
/** Fill viewport with background color */
326
static void mask_323(void *dst, bool mask)
333
static void
-
 
334
clear_port(viewport_t *vport)
-
 
335
{
327
{
336
    draw_rectangle(vport, 0, 0, vport->width, vport->height,
-
 
337
        vport->style.bg_color);
328
    *((uint8_t *) dst) = (mask ? 0xff : 0);
338
}
329
}
339
 
330
 
340
/** Scroll unbuffered viewport up/down
331
/** Draw a filled rectangle.
-
 
332
 *
-
 
333
 * @note Need real implementation that does not access VRAM twice.
341
 *
334
 *
342
 * @param vport Viewport to scroll
-
 
343
 * @param lines Positive number - scroll up, negative - scroll down
-
 
344
 */
335
 */
345
static void
336
static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1,
346
scroll_port_nodb(viewport_t *vport, int lines)
337
    unsigned int y1, uint32_t color)
347
{
338
{
-
 
339
    unsigned int x;
348
    int y;
340
    unsigned int y;
-
 
341
    unsigned int copy_bytes;
349
 
342
   
350
    if (lines > 0) {
343
    uint8_t *sp;
351
        for (y = vport->y; y < vport->y+vport->height - lines; y++)
-
 
352
            memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
-
 
353
                &screen.fbaddress[POINTPOS(vport->x,y + lines)],
-
 
354
                screen.pixelbytes * vport->width);
344
    uint8_t *dp;
355
        draw_rectangle(vport, 0, vport->height - lines, vport->width,
-
 
356
            lines, vport->style.bg_color);
345
    uint8_t cbuf[4];
-
 
346
   
357
    } else if (lines < 0) {
347
    if ((y0 >= y1) || (x0 >= x1))
358
        lines = -lines;
348
        return;
-
 
349
   
359
        for (y = vport->y + vport->height-1; y >= vport->y + lines; y--)
350
    screen.rgb_conv(cbuf, color);
-
 
351
   
360
            memcpy(&screen.fbaddress[POINTPOS(vport->x,y)],
352
    sp = &screen.fb_addr[FB_POS(x0, y0)];
-
 
353
    dp = sp;
-
 
354
   
361
                &screen.fbaddress[POINTPOS(vport->x,y - lines)],
355
    /* Draw the first line. */
362
                screen.pixelbytes * vport->width);
356
    for (x = x0; x < x1; x++) {
363
        draw_rectangle(vport, 0, 0, vport->width, lines,
357
        memcpy(dp, cbuf, screen.pixelbytes);
364
            vport->style.bg_color);
358
        dp += screen.pixelbytes;
365
    }
359
    }
366
}
360
   
367
 
-
 
368
/** Refresh given viewport from double buffer */
361
    dp = sp + screen.scanline;
369
static void
-
 
370
refresh_viewport_db(viewport_t *vport)
362
    copy_bytes = (x1 - x0) * screen.pixelbytes;
371
{
363
   
372
    unsigned int y, srcy, srcoff, dsty, dstx;
364
    /* Draw the remaining lines by copying. */
373
 
-
 
374
    for (y = 0; y < vport->height; y++) {
365
    for (y = y0 + 1; y < y1; y++) {
375
        srcy = (y + vport->dboffset) % vport->height;
-
 
376
        srcoff = (vport->width * srcy) * screen.pixelbytes;
-
 
377
 
-
 
378
        dstx = vport->x;
366
        memcpy(dp, sp, copy_bytes);
379
        dsty = vport->y + y;
367
        dp += screen.scanline;
380
 
-
 
381
        memcpy(&screen.fbaddress[POINTPOS(dstx,dsty)],
-
 
382
            &vport->dbdata[srcoff], vport->width * screen.pixelbytes);
-
 
383
    }
368
    }
384
}
369
}
385
 
370
 
-
 
371
/** Redraw viewport.
-
 
372
 *
386
/** Scroll viewport that has double buffering enabled */
373
 * @param vport Viewport to redraw
-
 
374
 *
387
static void
375
 */
388
scroll_port_db(viewport_t *vport, int lines)
376
static void vport_redraw(viewport_t *vport)
389
{
377
{
390
    ++vport->paused;
-
 
391
    if (lines > 0) {
378
    unsigned int row;
392
        draw_rectangle(vport, 0, 0, vport->width, lines,
-
 
393
            vport->style.bg_color);
-
 
394
        vport->dboffset += lines;
-
 
395
        vport->dboffset %= vport->height;
-
 
396
    } else if (lines < 0) {
-
 
397
        lines = -lines;
379
    unsigned int col;
398
        draw_rectangle(vport, 0, vport->height-lines, vport->width,
-
 
399
            lines, vport->style.bg_color);
-
 
400
 
380
   
401
        if (vport->dboffset < lines)
381
    for (row = 0; row < vport->rows; row++) {
402
            vport->dboffset += vport->height;
382
        for (col = 0; col < vport->cols; col++) {
403
        vport->dboffset -= lines;
383
            draw_vp_glyph(vport, false, col, row);
-
 
384
        }
404
    }
385
    }
405
   
386
   
-
 
387
    if (COL2X(vport->cols) < vport->width) {
-
 
388
        draw_filled_rect(
-
 
389
            vport->x + COL2X(vport->cols), vport->y,
-
 
390
            vport->x + vport->width, vport->y + vport->height,
406
    --vport->paused;
391
            vport->attr.bg_color);
-
 
392
    }
407
   
393
   
-
 
394
    if (ROW2Y(vport->rows) < vport->height) {
-
 
395
        draw_filled_rect(
-
 
396
            vport->x, vport->y + ROW2Y(vport->rows),
-
 
397
            vport->x + vport->width, vport->y + vport->height,
408
    refresh_viewport_db(vport);
398
            vport->attr.bg_color);
-
 
399
    }
409
}
400
}
410
 
401
 
411
/** Scrolls viewport given number of lines */
402
static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color,
412
static void
403
    uint32_t bg_color)
413
scroll_port(viewport_t *vport, int lines)
-
 
414
{
404
{
415
    if (vport->dbdata)
-
 
416
        scroll_port_db(vport, lines);
-
 
417
    else
405
    size_t i;
418
        scroll_port_nodb(vport, lines);
-
 
419
   
406
   
-
 
407
    for (i = 0; i < len; i++) {
-
 
408
        backbuf[i].glyph = 0;
-
 
409
        backbuf[i].fg_color = fg_color;
-
 
410
        backbuf[i].bg_color = bg_color;
-
 
411
    }
420
}
412
}
421
 
413
 
422
static void
414
/** Clear viewport.
-
 
415
 *
-
 
416
 * @param vport Viewport to clear
-
 
417
 *
-
 
418
 */
423
invert_pixel(viewport_t *vport, unsigned int x, unsigned int y)
419
static void vport_clear(viewport_t *vport)
424
{
420
{
425
    putpixel(vport, x, y, ~getpixel(vport, x, y));
421
    backbuf_clear(vport->backbuf, vport->cols * vport->rows,
-
 
422
        vport->attr.fg_color, vport->attr.bg_color);
-
 
423
    vport_redraw(vport);
426
}
424
}
427
 
425
 
-
 
426
/** Scroll viewport by the specified number of lines.
428
 
427
 *
429
/***************************************************************/
-
 
430
/* Character-console functions */
428
 * @param vport Viewport to scroll
431
 
-
 
432
/** Draw character at given position
429
 * @param lines Number of lines to scroll
433
 *
430
 *
434
 * @param vport Viewport where the character is printed
-
 
435
 * @param sx Coordinates of top-left of the character
-
 
436
 * @param sy Coordinates of top-left of the character
-
 
437
 * @param style Color of the character
-
 
438
 * @param transparent If false, print background color
-
 
439
 */
431
 */
440
static void
-
 
441
draw_glyph(viewport_t *vport,uint8_t glyph, unsigned int sx, unsigned int sy,
432
static void vport_scroll(viewport_t *vport, int lines)
442
    style_t style, int transparent)
-
 
443
{
433
{
-
 
434
    unsigned int row;
-
 
435
    unsigned int col;
444
    int i;
436
    unsigned int x;
445
    unsigned int y;
437
    unsigned int y;
446
    unsigned int glline;
438
    uint32_t glyph;
-
 
439
    uint32_t fg_color;
-
 
440
    uint32_t bg_color;
-
 
441
    bb_cell_t *bbp;
-
 
442
    bb_cell_t *xbp;
-
 
443
   
-
 
444
    /*
-
 
445
     * Redraw.
-
 
446
     */
447
 
447
   
-
 
448
    y = vport->y;
448
    for (y = 0; y < FONT_SCANLINES; y++) {
449
    for (row = 0; row < vport->rows; row++) {
-
 
450
        x = vport->x;
-
 
451
        for (col = 0; col < vport->cols; col++) {
-
 
452
            if ((row + lines >= 0) && (row + lines < vport->rows)) {
-
 
453
                xbp = &vport->backbuf[BB_POS(vport, col, row + lines)];
449
        glline = fb_font[glyph * FONT_SCANLINES + y];
454
                bbp = &vport->backbuf[BB_POS(vport, col, row)];
-
 
455
               
-
 
456
                glyph = xbp->glyph;
450
        for (i = 0; i < 8; i++) {
457
                fg_color = xbp->fg_color;
-
 
458
                bg_color = xbp->bg_color;
-
 
459
               
451
            if (glline & (1 << (7 - i)))
460
                if ((bbp->glyph == glyph)
452
                putpixel(vport, sx + i, sy + y, style.fg_color);
461
                   && (bbp->fg_color == xbp->fg_color)
-
 
462
                   && (bbp->bg_color == xbp->bg_color)) {
453
            else if (!transparent)
463
                    x += FONT_WIDTH;
-
 
464
                    continue;
-
 
465
                }
-
 
466
            } else {
-
 
467
                glyph = 0;
-
 
468
                fg_color = vport->attr.fg_color;
454
                putpixel(vport, sx + i, sy + y, style.bg_color);
469
                bg_color = vport->attr.bg_color;
-
 
470
            }
-
 
471
           
-
 
472
            (*vport->dglyph)(x, y, false, screen.glyphs, glyph,
-
 
473
                fg_color, bg_color);
-
 
474
            x += FONT_WIDTH;
455
        }
475
        }
-
 
476
        y += FONT_SCANLINES;
-
 
477
    }
-
 
478
   
-
 
479
    /*
-
 
480
     * Scroll backbuffer.
-
 
481
     */
-
 
482
   
-
 
483
    if (lines > 0) {
-
 
484
        memmove(vport->backbuf, vport->backbuf + vport->cols * lines,
-
 
485
            vport->cols * (vport->rows - lines) * sizeof(bb_cell_t));
-
 
486
        backbuf_clear(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)],
-
 
487
            vport->cols * lines, vport->attr.fg_color, vport->attr.bg_color);
-
 
488
    } else {
-
 
489
        memmove(vport->backbuf - vport->cols * lines, vport->backbuf,
-
 
490
            vport->cols * (vport->rows + lines) * sizeof(bb_cell_t));
-
 
491
        backbuf_clear(vport->backbuf, - vport->cols * lines,
-
 
492
            vport->attr.fg_color, vport->attr.bg_color);
456
    }
493
    }
457
}
494
}
458
 
495
 
-
 
496
/** Render glyphs
-
 
497
 *
459
/** Invert character at given position */
498
 * Convert glyphs from device independent font
-
 
499
 * description to current visual representation.
-
 
500
 *
460
static void
501
 */
461
invert_char(viewport_t *vport,unsigned int row, unsigned int col)
502
static void render_glyphs(void)
462
{
503
{
463
    unsigned int x;
504
    unsigned int glyph;
-
 
505
   
-
 
506
    for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
464
    unsigned int y;
507
        unsigned int y;
465
 
508
       
466
    for (x = 0; x < COL_WIDTH; x++)
509
        for (y = 0; y < FONT_SCANLINES; y++) {
-
 
510
            unsigned int x;
-
 
511
           
467
        for (y = 0; y < FONT_SCANLINES; y++)
512
            for (x = 0; x < FONT_WIDTH; x++) {
-
 
513
                screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes],
468
            invert_pixel(vport, col * COL_WIDTH + x, row *
514
                    (fb_font[glyph][y] & (1 << (7 - x))) ? true : false);
-
 
515
               
-
 
516
                screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes],
469
                FONT_SCANLINES + y);
517
                    (fb_font[glyph][y] & (1 << (7 - x))) ? false : true);
-
 
518
            }
-
 
519
        }
-
 
520
    }
470
}
521
}
471
 
522
 
472
/***************************************************************/
-
 
473
/* Stdout specific functions */
-
 
474
 
-
 
475
 
-
 
476
/** Create new viewport
523
/** Create new viewport
477
 *
524
 *
-
 
525
 * @param x      Origin of the viewport (x).
-
 
526
 * @param y      Origin of the viewport (y).
-
 
527
 * @param width  Width of the viewport.
-
 
528
 * @param height Height of the viewport.
-
 
529
 *
478
 * @return New viewport number
530
 * @return New viewport number.
-
 
531
 *
479
 */
532
 */
480
static int
-
 
481
viewport_create(unsigned int x, unsigned int y,unsigned int width,
533
static int vport_create(unsigned int x, unsigned int y,
482
    unsigned int height)
534
    unsigned int width, unsigned int height)
483
{
535
{
484
    int i;
536
    unsigned int i;
485
 
537
   
486
    for (i = 0; i < MAX_VIEWPORTS; i++) {
538
    for (i = 0; i < MAX_VIEWPORTS; i++) {
487
        if (!viewports[i].initialized)
539
        if (!viewports[i].initialized)
488
            break;
540
            break;
489
    }
541
    }
-
 
542
   
490
    if (i == MAX_VIEWPORTS)
543
    if (i == MAX_VIEWPORTS)
491
        return ELIMIT;
544
        return ELIMIT;
492
 
545
   
-
 
546
    unsigned int cols = width / FONT_WIDTH;
-
 
547
    unsigned int rows = height / FONT_SCANLINES;
-
 
548
    unsigned int bbsize = cols * rows * sizeof(bb_cell_t);
-
 
549
    unsigned int word_size = sizeof(unsigned long);
-
 
550
   
-
 
551
    bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize);
-
 
552
    if (!backbuf)
-
 
553
        return ENOMEM;
-
 
554
   
-
 
555
    uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes);
-
 
556
    if (!bgpixel) {
-
 
557
        free(backbuf);
-
 
558
        return ENOMEM;
-
 
559
    }
-
 
560
   
-
 
561
    backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR);
-
 
562
    memset(bgpixel, 0, screen.pixelbytes);
-
 
563
   
493
    viewports[i].x = x;
564
    viewports[i].x = x;
494
    viewports[i].y = y;
565
    viewports[i].y = y;
495
    viewports[i].width = width;
566
    viewports[i].width = width;
496
    viewports[i].height = height;
567
    viewports[i].height = height;
497
   
568
   
498
    viewports[i].rows = height / FONT_SCANLINES;
569
    viewports[i].cols = cols;
499
    viewports[i].cols = width / COL_WIDTH;
570
    viewports[i].rows = rows;
500
 
571
   
501
    viewports[i].style.bg_color = DEFAULT_BGCOLOR;
572
    viewports[i].attr.bg_color = DEFAULT_BGCOLOR;
502
    viewports[i].style.fg_color = DEFAULT_FGCOLOR;
573
    viewports[i].attr.fg_color = DEFAULT_FGCOLOR;
-
 
574
   
-
 
575
    viewports[i].bgpixel = bgpixel;
-
 
576
   
-
 
577
    /*
-
 
578
     * Conditions necessary to select aligned version:
-
 
579
     *  - word size is divisible by pixelbytes
-
 
580
     *  - cell scanline size is divisible by word size
-
 
581
     *  - cell scanlines are word-aligned
-
 
582
     *
-
 
583
     */
-
 
584
    if (((word_size % screen.pixelbytes) == 0)
-
 
585
        && ((FONT_WIDTH * screen.pixelbytes) % word_size == 0)
-
 
586
        && ((x * screen.pixelbytes) % word_size == 0)
-
 
587
        && (screen.scanline % word_size == 0)) {
-
 
588
        viewports[i].dglyph = draw_glyph_aligned;
-
 
589
    } else {
-
 
590
        viewports[i].dglyph = draw_glyph_fallback;
-
 
591
    }
503
   
592
   
504
    viewports[i].cur_col = 0;
593
    viewports[i].cur_col = 0;
505
    viewports[i].cur_row = 0;
594
    viewports[i].cur_row = 0;
506
    viewports[i].cursor_active = 0;
595
    viewports[i].cursor_active = false;
-
 
596
    viewports[i].cursor_shown = false;
-
 
597
   
-
 
598
    viewports[i].bbsize = bbsize;
-
 
599
    viewports[i].backbuf = backbuf;
507
 
600
   
508
    viewports[i].initialized = 1;
601
    viewports[i].initialized = true;
-
 
602
   
-
 
603
    screen.rgb_conv(viewports[i].bgpixel, viewports[i].attr.bg_color);
509
 
604
   
510
    return i;
605
    return i;
511
}
606
}
512
 
607
 
-
 
608
 
513
/** Initialize framebuffer as a chardev output device
609
/** Initialize framebuffer as a chardev output device
514
 *
610
 *
515
 * @param addr          Address of theframebuffer
611
 * @param addr   Address of the framebuffer
516
 * @param xres          Screen width in pixels
612
 * @param xres   Screen width in pixels
517
 * @param yres          Screen height in pixels
613
 * @param yres   Screen height in pixels
518
 * @param visual        Bits per pixel (8, 16, 24, 32)
614
 * @param visual Bits per pixel (8, 16, 24, 32)
519
 * @param scan          Bytes per one scanline
615
 * @param scan   Bytes per one scanline
520
 * @param invert_colors Inverted colors.
-
 
521
 *
616
 *
522
 */
617
 */
523
static bool
-
 
524
screen_init(void *addr, unsigned int offset, unsigned int xres,
618
static bool screen_init(void *addr, unsigned int xres, unsigned int yres,
525
    unsigned int yres, unsigned int scan, unsigned int visual,
619
    unsigned int scan, unsigned int visual)
526
    bool invert_colors)
-
 
527
{
620
{
-
 
621
   
-
 
622
   
528
    switch (visual) {
623
    switch (visual) {
529
    case VISUAL_INDIRECT_8:
624
    case VISUAL_INDIRECT_8:
530
        screen.rgb2scr = rgb_byte8;
625
        screen.rgb_conv = rgb_323;
531
        screen.scr2rgb = byte8_rgb;
626
        screen.mask_conv = mask_323;
532
        screen.pixelbytes = 1;
627
        screen.pixelbytes = 1;
533
        break;
628
        break;
534
    case VISUAL_RGB_5_5_5:
629
    case VISUAL_RGB_5_5_5:
535
        screen.rgb2scr = rgb_byte555;
630
        screen.rgb_conv = rgb_555;
536
        screen.scr2rgb = byte555_rgb;
631
        screen.mask_conv = mask_555;
537
        screen.pixelbytes = 2;
632
        screen.pixelbytes = 2;
538
        break;
633
        break;
539
    case VISUAL_RGB_5_6_5:
634
    case VISUAL_RGB_5_6_5:
540
        screen.rgb2scr = rgb_byte565;
635
        screen.rgb_conv = rgb_565;
541
        screen.scr2rgb = byte565_rgb;
636
        screen.mask_conv = mask_565;
542
        screen.pixelbytes = 2;
637
        screen.pixelbytes = 2;
543
        break;
638
        break;
544
    case VISUAL_RGB_8_8_8:
639
    case VISUAL_RGB_8_8_8:
545
        screen.rgb2scr = rgb_byte888;
640
        screen.rgb_conv = rgb_888;
-
 
641
        screen.mask_conv = mask_888;
-
 
642
        screen.pixelbytes = 3;
-
 
643
        break;
-
 
644
    case VISUAL_BGR_8_8_8:
546
        screen.scr2rgb = byte888_rgb;
645
        screen.rgb_conv = bgr_888;
-
 
646
        screen.mask_conv = mask_888;
547
        screen.pixelbytes = 3;
647
        screen.pixelbytes = 3;
548
        break;
648
        break;
549
    case VISUAL_RGB_8_8_8_0:
649
    case VISUAL_RGB_8_8_8_0:
550
        screen.rgb2scr = rgb_byte888;
650
        screen.rgb_conv = rgb_888;
551
        screen.scr2rgb = byte888_rgb;
651
        screen.mask_conv = mask_888;
552
        screen.pixelbytes = 4;
652
        screen.pixelbytes = 4;
553
        break;
653
        break;
554
    case VISUAL_RGB_0_8_8_8:
654
    case VISUAL_RGB_0_8_8_8:
555
        screen.rgb2scr = rgb_byte0888;
655
        screen.rgb_conv = rgb_0888;
556
        screen.scr2rgb = byte0888_rgb;
656
        screen.mask_conv = mask_0888;
557
        screen.pixelbytes = 4;
657
        screen.pixelbytes = 4;
558
        break;
658
        break;
559
    case VISUAL_BGR_0_8_8_8:
659
    case VISUAL_BGR_0_8_8_8:
560
        screen.rgb2scr = bgr_byte0888;
660
        screen.rgb_conv = bgr_0888;
561
        screen.scr2rgb = byte0888_bgr;
661
        screen.mask_conv = mask_0888;
562
        screen.pixelbytes = 4;
662
        screen.pixelbytes = 4;
563
        break;
663
        break;
564
    default:
664
    default:
565
        return false;
665
        return false;
566
    }
666
    }
567
 
667
   
568
    screen.fbaddress = (unsigned char *) (((uintptr_t) addr) + offset);
668
    screen.fb_addr = (unsigned char *) addr;
569
    screen.xres = xres;
669
    screen.xres = xres;
570
    screen.yres = yres;
670
    screen.yres = yres;
571
    screen.scanline = scan;
671
    screen.scanline = scan;
-
 
672
   
-
 
673
    screen.glyphscanline = FONT_WIDTH * screen.pixelbytes;
-
 
674
    screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES;
-
 
675
   
-
 
676
    size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes;
-
 
677
    uint8_t *glyphs = (uint8_t *) malloc(glyphsize);
-
 
678
    if (!glyphs)
-
 
679
        return false;
-
 
680
   
-
 
681
    memset(glyphs, 0, glyphsize);
572
    screen.invert_colors = invert_colors;
682
    screen.glyphs = glyphs;
-
 
683
   
-
 
684
    render_glyphs();
573
   
685
   
574
    /* Create first viewport */
686
    /* Create first viewport */
575
    viewport_create(0, 0, xres, yres);
687
    vport_create(0, 0, xres, yres);
576
   
688
   
577
    return true;
689
    return true;
578
}
690
}
579
 
691
 
-
 
692
 
-
 
693
/** Draw a glyph, takes advantage of alignment.
-
 
694
 *
-
 
695
 * This version can only be used if the following conditions are met:
-
 
696
 *
-
 
697
 *   - word size is divisible by pixelbytes
-
 
698
 *   - cell scanline size is divisible by word size
-
 
699
 *   - cell scanlines are word-aligned
-
 
700
 *
-
 
701
 * It makes use of the pre-rendered mask to process (possibly) several
-
 
702
 * pixels at once (word size / pixelbytes pixels at a time are processed)
-
 
703
 * making it very fast. Most notably this version is not applicable at 24 bits
-
 
704
 * per pixel.
-
 
705
 *
-
 
706
 * @param x        x coordinate of top-left corner on screen.
-
 
707
 * @param y        y coordinate of top-left corner on screen.
-
 
708
 * @param cursor   Draw glyph with cursor
-
 
709
 * @param glyphs   Pointer to font bitmap.
-
 
710
 * @param glyph    Code of the glyph to draw.
-
 
711
 * @param fg_color Foreground color.
-
 
712
 * @param bg_color Backgroudn color.
-
 
713
 *
-
 
714
 */
-
 
715
static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
-
 
716
    uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color)
-
 
717
{
-
 
718
    unsigned int i;
-
 
719
    unsigned int yd;
-
 
720
    unsigned long fg_buf;
-
 
721
    unsigned long bg_buf;
-
 
722
    unsigned long mask;
-
 
723
   
-
 
724
    /*
-
 
725
     * Prepare a pair of words, one filled with foreground-color
-
 
726
     * pattern and the other filled with background-color pattern.
-
 
727
     */
-
 
728
    for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) {
-
 
729
        screen.rgb_conv(&((uint8_t *) &fg_buf)[i * screen.pixelbytes],
-
 
730
            fg_color);
-
 
731
        screen.rgb_conv(&((uint8_t *) &bg_buf)[i * screen.pixelbytes],
-
 
732
            bg_color);
-
 
733
    }
-
 
734
   
-
 
735
    /* Pointer to the current position in the mask. */
-
 
736
    unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)];
-
 
737
   
-
 
738
    /* Pointer to the current position on the screen. */
-
 
739
    unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)];
-
 
740
   
-
 
741
    /* Width of the character cell in words. */
-
 
742
    unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long);
-
 
743
   
-
 
744
    /* Offset to add when moving to another screen scanline. */
-
 
745
    unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;
-
 
746
   
-
 
747
    for (yd = 0; yd < FONT_SCANLINES; yd++) {
-
 
748
        /*
-
 
749
         * Now process the cell scanline, combining foreground
-
 
750
         * and background color patters using the pre-rendered mask.
-
 
751
         */
-
 
752
        for (i = 0; i < ww; i++) {
-
 
753
            mask = *maskp++;
-
 
754
            *dp++ = (fg_buf & mask) | (bg_buf & ~mask);
-
 
755
        }
-
 
756
       
-
 
757
        /* Move to the beginning of the next scanline of the cell. */
-
 
758
        dp = (unsigned long *) ((uint8_t *) dp + d_add);
-
 
759
    }
-
 
760
}
-
 
761
 
-
 
762
/** Draw a glyph, fallback version.
-
 
763
 *
-
 
764
 * This version does not make use of the pre-rendered mask, it uses
-
 
765
 * the font bitmap directly. It works always, but it is slower.
-
 
766
 *
-
 
767
 * @param x        x coordinate of top-left corner on screen.
-
 
768
 * @param y        y coordinate of top-left corner on screen.
-
 
769
 * @param cursor   Draw glyph with cursor
-
 
770
 * @param glyphs   Pointer to font bitmap.
-
 
771
 * @param glyph    Code of the glyph to draw.
-
 
772
 * @param fg_color Foreground color.
-
 
773
 * @param bg_color Backgroudn color.
-
 
774
 *
-
 
775
 */
-
 
776
void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,
-
 
777
    uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color)
-
 
778
{
-
 
779
    unsigned int i;
-
 
780
    unsigned int j;
-
 
781
    unsigned int yd;
-
 
782
    uint8_t fg_buf[4];
-
 
783
    uint8_t bg_buf[4];
-
 
784
    uint8_t *sp;
-
 
785
    uint8_t b;
-
 
786
   
-
 
787
    /* Pre-render 1x the foreground and background color pixels. */
-
 
788
    if (cursor) {
-
 
789
        screen.rgb_conv(fg_buf, bg_color);
-
 
790
        screen.rgb_conv(bg_buf, fg_color);
-
 
791
    } else {
-
 
792
        screen.rgb_conv(fg_buf, fg_color);
-
 
793
        screen.rgb_conv(bg_buf, bg_color);
-
 
794
    }
-
 
795
   
-
 
796
    /* Pointer to the current position on the screen. */
-
 
797
    uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)];
-
 
798
   
-
 
799
    /* Offset to add when moving to another screen scanline. */
-
 
800
    unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;
-
 
801
   
-
 
802
    for (yd = 0; yd < FONT_SCANLINES; yd++) {
-
 
803
        /* Byte containing bits of the glyph scanline. */
-
 
804
        b = fb_font[glyph][yd];
-
 
805
       
-
 
806
        for (i = 0; i < FONT_WIDTH; i++) {
-
 
807
            /* Choose color based on the current bit. */
-
 
808
            sp = (b & 0x80) ? fg_buf : bg_buf;
-
 
809
           
-
 
810
            /* Copy the pixel. */
-
 
811
            for (j = 0; j < screen.pixelbytes; j++) {
-
 
812
                *dp++ = *sp++;
-
 
813
            }
-
 
814
           
-
 
815
            /* Move to the next bit. */
-
 
816
            b = b << 1;
-
 
817
        }
-
 
818
       
-
 
819
        /* Move to the beginning of the next scanline of the cell. */
-
 
820
        dp += d_add;
-
 
821
    }
-
 
822
}
-
 
823
 
-
 
824
/** Draw glyph at specified position in viewport.
-
 
825
 *
-
 
826
 * @param vport  Viewport identification
-
 
827
 * @param cursor Draw glyph with cursor
-
 
828
 * @param col    Screen position relative to viewport
-
 
829
 * @param row    Screen position relative to viewport
-
 
830
 *
-
 
831
 */
-
 
832
static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
-
 
833
    unsigned int row)
-
 
834
{
-
 
835
    unsigned int x = vport->x + COL2X(col);
-
 
836
    unsigned int y = vport->y + ROW2Y(row);
-
 
837
   
-
 
838
    uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph;
-
 
839
    uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color;
-
 
840
    uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color;
-
 
841
   
-
 
842
    (*vport->dglyph)(x, y, cursor, screen.glyphs, glyph,
-
 
843
        fg_color, bg_color);
-
 
844
}
-
 
845
 
580
/** Hide cursor if it is shown */
846
/** Hide cursor if it is shown
-
 
847
 *
581
static void
848
 */
582
cursor_hide(viewport_t *vport)
849
static void cursor_hide(viewport_t *vport)
583
{
850
{
584
    if (vport->cursor_active && vport->cursor_shown) {
851
    if ((vport->cursor_active) && (vport->cursor_shown)) {
585
        invert_char(vport, vport->cur_row, vport->cur_col);
852
        draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row);
586
        vport->cursor_shown = 0;
853
        vport->cursor_shown = false;
587
    }
854
    }
588
}
855
}
589
 
856
 
-
 
857
 
590
/** Show cursor if cursor showing is enabled */
858
/** Show cursor if cursor showing is enabled
-
 
859
 *
591
static void
860
 */
592
cursor_print(viewport_t *vport)
861
static void cursor_show(viewport_t *vport)
593
{
862
{
594
    /* Do not check for cursor_shown */
863
    /* Do not check for cursor_shown */
595
    if (vport->cursor_active) {
864
    if (vport->cursor_active) {
596
        invert_char(vport, vport->cur_row, vport->cur_col);
865
        draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row);
597
        vport->cursor_shown = 1;
866
        vport->cursor_shown = true;
598
    }
867
    }
599
}
868
}
600
 
869
 
-
 
870
 
601
/** Invert cursor, if it is enabled */
871
/** Invert cursor, if it is enabled
-
 
872
 *
602
static void
873
 */
603
cursor_blink(viewport_t *vport)
874
static void cursor_blink(viewport_t *vport)
604
{
875
{
605
    if (vport->cursor_shown)
876
    if (vport->cursor_shown)
606
        cursor_hide(vport);
877
        cursor_hide(vport);
607
    else
878
    else
608
        cursor_print(vport);
879
        cursor_show(vport);
609
}
880
}
610
 
881
 
611
/** Draw character at given position relative to viewport
-
 
612
 *
-
 
613
 * @param vport Viewport identification
-
 
614
 * @param c Character to print
-
 
615
 * @param row Screen position relative to viewport
-
 
616
 * @param col Screen position relative to viewport
-
 
617
 * @param transparent If false, print background color with character
-
 
618
 */
-
 
619
static void
-
 
620
draw_char(viewport_t *vport, char c, unsigned int row, unsigned int col,
-
 
621
    style_t style, int transparent)
-
 
622
{
-
 
623
    /* Optimize - do not hide cursor if we are going to overwrite it */
-
 
624
    if (vport->cursor_active && vport->cursor_shown &&
-
 
625
        (vport->cur_col != col || vport->cur_row != row))
-
 
626
        invert_char(vport, vport->cur_row, vport->cur_col);
-
 
627
   
-
 
628
    draw_glyph(vport, c, col * COL_WIDTH, row * FONT_SCANLINES, style,
-
 
629
        transparent);
-
 
630
 
882
 
-
 
883
/** Draw character at given position relative to viewport
-
 
884
 *
-
 
885
 * @param vport  Viewport identification
-
 
886
 * @param c      Character to draw
-
 
887
 * @param col    Screen position relative to viewport
-
 
888
 * @param row    Screen position relative to viewport
-
 
889
 *
-
 
890
 */
-
 
891
static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row)
-
 
892
{
-
 
893
    bb_cell_t *bbp;
-
 
894
   
-
 
895
    /* Do not hide cursor if we are going to overwrite it */
-
 
896
    if ((vport->cursor_active) && (vport->cursor_shown) &&
-
 
897
        ((vport->cur_col != col) || (vport->cur_row != row)))
-
 
898
        cursor_hide(vport);
-
 
899
   
-
 
900
    bbp = &vport->backbuf[BB_POS(vport, col, row)];
-
 
901
    bbp->glyph = fb_font_glyph(c);
-
 
902
    bbp->fg_color = vport->attr.fg_color;
-
 
903
    bbp->bg_color = vport->attr.bg_color;
-
 
904
   
-
 
905
    draw_vp_glyph(vport, false, col, row);
-
 
906
   
631
    vport->cur_col = col;
907
    vport->cur_col = col;
632
    vport->cur_row = row;
908
    vport->cur_row = row;
633
 
909
   
634
    vport->cur_col++;
910
    vport->cur_col++;
635
    if (vport->cur_col >= vport->cols) {
911
    if (vport->cur_col >= vport->cols) {
636
        vport->cur_col = 0;
912
        vport->cur_col = 0;
637
        vport->cur_row++;
913
        vport->cur_row++;
638
        if (vport->cur_row >= vport->rows)
914
        if (vport->cur_row >= vport->rows)
639
            vport->cur_row--;
915
            vport->cur_row--;
640
    }
916
    }
-
 
917
   
641
    cursor_print(vport);
918
    cursor_show(vport);
642
}
919
}
643
 
920
 
644
/** Draw text data to viewport
921
/** Draw text data to viewport.
645
 *
922
 *
646
 * @param vport Viewport id
923
 * @param vport Viewport id
-
 
924
 * @param data  Text data.
647
 * @param data Text data fitting exactly into viewport
925
 * @param x     Leftmost column of the area.
-
 
926
 * @param y     Topmost row of the area.
-
 
927
 * @param w     Number of rows.
-
 
928
 * @param h     Number of columns.
-
 
929
 *
648
 */
930
 */
649
static void
-
 
650
draw_text_data(viewport_t *vport, keyfield_t *data)
931
static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x,
-
 
932
    unsigned int y, unsigned int w, unsigned int h)
651
{
933
{
652
    int i;
934
    unsigned int i;
-
 
935
    unsigned int j;
-
 
936
    bb_cell_t *bbp;
653
    int col,row;
937
    attrs_t *a;
-
 
938
    attr_rgb_t rgb;
654
 
939
   
655
    clear_port(vport);
940
    for (j = 0; j < h; j++) {
656
    for (i = 0; i < vport->cols * vport->rows; i++) {
941
        for (i = 0; i < w; i++) {
657
        if (data[i].character == ' ' && style_same(data[i].style,
942
            unsigned int col = x + i;
658
            vport->style))
943
            unsigned int row = y + j;
-
 
944
           
-
 
945
            bbp = &vport->backbuf[BB_POS(vport, col, row)];
659
            continue;
946
           
660
        col = i % vport->cols;
947
            a = &data[j * w + i].attrs;
661
        row = i / vport->cols;
948
            rgb_from_attr(&rgb, a);
-
 
949
           
662
        draw_glyph(vport, data[i].character, col * COL_WIDTH, row *
950
            bbp->glyph = fb_font_glyph(data[j * w + i].character);
-
 
951
            bbp->fg_color = rgb.fg_color;
663
            FONT_SCANLINES, data[i].style, style_same(data[i].style,
952
            bbp->bg_color = rgb.bg_color;
-
 
953
           
664
            vport->style));
954
            draw_vp_glyph(vport, false, col, row);
-
 
955
        }
665
    }
956
    }
666
    cursor_print(vport);
957
    cursor_show(vport);
667
}
958
}
668
 
959
 
669
/** Return first free pixmap */
-
 
670
static int
960
 
671
find_free_pixmap(void)
961
static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
672
{
962
{
673
    int i;
963
    int pm = *((int *) data);
-
 
964
    pixmap_t *pmap = &pixmaps[pm];
-
 
965
    unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
674
   
966
   
675
    for (i = 0;i < MAX_PIXMAPS;i++)
967
    screen.rgb_conv(&pmap->data[pos], color);
676
        if (!pixmaps[i].data)
-
 
677
            return i;
-
 
678
    return -1;
-
 
679
}
968
}
680
 
969
 
681
static void
970
 
682
putpixel_pixmap(int pm, unsigned int x, unsigned int y, int color)
971
static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
683
{
972
{
-
 
973
    viewport_t *vport = (viewport_t *) data;
-
 
974
    unsigned int dx = vport->x + x;
684
    pixmap_t *pmap = &pixmaps[pm];
975
    unsigned int dy = vport->y + y;
-
 
976
   
685
    int pos = (y * pmap->width + x) * screen.pixelbytes;
977
    screen.rgb_conv(&screen.fb_addr[FB_POS(dx, dy)], color);
-
 
978
}
-
 
979
 
686
 
980
 
-
 
981
/** Return first free pixmap
-
 
982
 *
-
 
983
 */
687
    (*screen.rgb2scr)(&pmap->data[pos],COLOR(color));
984
static int find_free_pixmap(void)
-
 
985
{
-
 
986
    unsigned int i;
-
 
987
   
-
 
988
    for (i = 0; i < MAX_PIXMAPS; i++)
-
 
989
        if (!pixmaps[i].data)
-
 
990
            return i;
-
 
991
   
-
 
992
    return -1;
688
}
993
}
689
 
994
 
-
 
995
 
690
/** Create a new pixmap and return appropriate ID */
996
/** Create a new pixmap and return appropriate ID
-
 
997
 *
691
static int
998
 */
692
shm2pixmap(unsigned char *shm, size_t size)
999
static int shm2pixmap(unsigned char *shm, size_t size)
693
{
1000
{
694
    int pm;
1001
    int pm;
695
    pixmap_t *pmap;
1002
    pixmap_t *pmap;
696
 
1003
   
697
    pm = find_free_pixmap();
1004
    pm = find_free_pixmap();
698
    if (pm == -1)
1005
    if (pm == -1)
699
        return ELIMIT;
1006
        return ELIMIT;
-
 
1007
   
700
    pmap = &pixmaps[pm];
1008
    pmap = &pixmaps[pm];
701
   
1009
   
702
    if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
1010
    if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
703
        return EINVAL;
1011
        return EINVAL;
704
   
1012
   
705
    pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
1013
    pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
706
    if (!pmap->data)
1014
    if (!pmap->data)
707
        return ENOMEM;
1015
        return ENOMEM;
708
 
1016
   
709
    ppm_draw(shm, size, 0, 0, pmap->width, pmap->height,
1017
    ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
710
        (putpixel_cb_t)putpixel_pixmap, (void *)pm);
-
 
711
 
1018
   
712
    return pm;
1019
    return pm;
713
}
1020
}
714
 
1021
 
-
 
1022
 
715
/** Handle shared memory communication calls
1023
/** Handle shared memory communication calls
716
 *
1024
 *
717
 * Protocol for drawing pixmaps:
1025
 * Protocol for drawing pixmaps:
718
 * - FB_PREPARE_SHM(client shm identification)
1026
 * - FB_PREPARE_SHM(client shm identification)
719
 * - IPC_M_AS_AREA_SEND
1027
 * - IPC_M_AS_AREA_SEND
720
 * - FB_DRAW_PPM(startx,starty)
1028
 * - FB_DRAW_PPM(startx, starty)
721
 * - FB_DROP_SHM
1029
 * - FB_DROP_SHM
722
 *
1030
 *
723
 * Protocol for text drawing
1031
 * Protocol for text drawing
724
 * - IPC_M_AS_AREA_SEND
1032
 * - IPC_M_AS_AREA_SEND
725
 * - FB_DRAW_TEXT_DATA
1033
 * - FB_DRAW_TEXT_DATA
726
 *
1034
 *
727
 * @param callid Callid of the current call
1035
 * @param callid Callid of the current call
728
 * @param call Current call data
1036
 * @param call   Current call data
729
 * @param vp Active viewport
1037
 * @param vp     Active viewport
-
 
1038
 *
730
 * @return 0 if the call was not handled byt this function, 1 otherwise
1039
 * @return false if the call was not handled byt this function, true otherwise
731
 *
1040
 *
732
 * note: this function is not threads safe, you would have
1041
 * Note: this function is not threads safe, you would have
733
 * to redefine static variables with __thread
1042
 * to redefine static variables with __thread
-
 
1043
 *
734
 */
1044
 */
735
static int
-
 
736
shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
1045
static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
737
{
1046
{
738
    static keyfield_t *interbuffer = NULL;
1047
    static keyfield_t *interbuffer = NULL;
739
    static size_t intersize = 0;
1048
    static size_t intersize = 0;
740
 
1049
   
741
    static unsigned char *shm = NULL;
1050
    static unsigned char *shm = NULL;
742
    static ipcarg_t shm_id = 0;
1051
    static ipcarg_t shm_id = 0;
743
    static size_t shm_size;
1052
    static size_t shm_size;
744
 
1053
   
745
    int handled = 1;
1054
    bool handled = true;
746
    int retval = 0;
1055
    int retval = EOK;
747
    viewport_t *vport = &viewports[vp];
1056
    viewport_t *vport = &viewports[vp];
-
 
1057
    unsigned int x;
748
    unsigned int x, y;
1058
    unsigned int y;
-
 
1059
    unsigned int w;
-
 
1060
    unsigned int h;
749
 
1061
   
750
    switch (IPC_GET_METHOD(*call)) {
1062
    switch (IPC_GET_METHOD(*call)) {
751
    case IPC_M_SHARE_OUT:
1063
    case IPC_M_SHARE_OUT:
752
        /* We accept one area for data interchange */
1064
        /* We accept one area for data interchange */
753
        if (IPC_GET_ARG1(*call) == shm_id) {
1065
        if (IPC_GET_ARG1(*call) == shm_id) {
754
            void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
1066
            void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
755
            shm_size = IPC_GET_ARG2(*call);
1067
            shm_size = IPC_GET_ARG2(*call);
756
            if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
1068
            if (!ipc_answer_1(callid, EOK, (sysarg_t) dest))
757
                shm = dest;
1069
                shm = dest;
758
            else
1070
            else
759
                shm_id = 0;
1071
                shm_id = 0;
-
 
1072
           
760
            if (shm[0] != 'P')
1073
            if (shm[0] != 'P')
761
                while (1)
1074
                return false;
762
                    ;
1075
           
763
            return 1;
1076
            return true;
764
        } else {
1077
        } else {
765
            intersize = IPC_GET_ARG2(*call);
1078
            intersize = IPC_GET_ARG2(*call);
766
            receive_comm_area(callid, call, (void *) &interbuffer);
1079
            receive_comm_area(callid, call, (void *) &interbuffer);
767
        }
1080
        }
768
        return 1;
1081
        return true;
769
    case FB_PREPARE_SHM:
1082
    case FB_PREPARE_SHM:
770
        if (shm_id)
1083
        if (shm_id)
771
            retval = EBUSY;
1084
            retval = EBUSY;
772
        else
1085
        else
773
            shm_id = IPC_GET_ARG1(*call);
1086
            shm_id = IPC_GET_ARG1(*call);
Line 778... Line 1091...
778
            as_area_destroy(shm);
1091
            as_area_destroy(shm);
779
            shm = NULL;
1092
            shm = NULL;
780
        }
1093
        }
781
        shm_id = 0;
1094
        shm_id = 0;
782
        break;
1095
        break;
783
 
1096
       
784
    case FB_SHM2PIXMAP:
1097
    case FB_SHM2PIXMAP:
785
        if (!shm) {
1098
        if (!shm) {
786
            retval = EINVAL;
1099
            retval = EINVAL;
787
            break;
1100
            break;
788
        }
1101
        }
Line 793... Line 1106...
793
            retval = EINVAL;
1106
            retval = EINVAL;
794
            break;
1107
            break;
795
        }
1108
        }
796
        x = IPC_GET_ARG1(*call);
1109
        x = IPC_GET_ARG1(*call);
797
        y = IPC_GET_ARG2(*call);
1110
        y = IPC_GET_ARG2(*call);
-
 
1111
       
798
        if (x > vport->width || y > vport->height) {
1112
        if ((x > vport->width) || (y > vport->height)) {
799
            retval = EINVAL;
1113
            retval = EINVAL;
800
            break;
1114
            break;
801
        }
1115
        }
802
       
1116
       
803
        ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
1117
        ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
804
            IPC_GET_ARG2(*call), vport->width - x, vport->height - y,
1118
            IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
805
            (putpixel_cb_t)putpixel, vport);
-
 
806
        break;
1119
        break;
807
    case FB_DRAW_TEXT_DATA:
1120
    case FB_DRAW_TEXT_DATA:
-
 
1121
        x = IPC_GET_ARG1(*call);
-
 
1122
        y = IPC_GET_ARG2(*call);
-
 
1123
        w = IPC_GET_ARG3(*call);
-
 
1124
        h = IPC_GET_ARG4(*call);
808
        if (!interbuffer) {
1125
        if (!interbuffer) {
809
            retval = EINVAL;
1126
            retval = EINVAL;
810
            break;
1127
            break;
811
        }
1128
        }
812
        if (intersize < vport->cols * vport->rows *
1129
        if (x + w > vport->cols || y + h > vport->rows) {
813
            sizeof(*interbuffer)) {
-
 
814
            retval = EINVAL;
1130
            retval = EINVAL;
815
            break;
1131
            break;
816
        }
1132
        }
-
 
1133
        if (intersize < w * h * sizeof(*interbuffer)) {
-
 
1134
            retval = EINVAL;
-
 
1135
            break;
-
 
1136
        }
817
        draw_text_data(vport, interbuffer);
1137
        draw_text_data(vport, interbuffer, x, y, w, h);
818
        break;
1138
        break;
819
    default:
1139
    default:
820
        handled = 0;
1140
        handled = false;
821
    }
1141
    }
822
   
1142
   
823
    if (handled)
1143
    if (handled)
824
        ipc_answer_0(callid, retval);
1144
        ipc_answer_0(callid, retval);
825
    return handled;
1145
    return handled;
826
}
1146
}
827
 
1147
 
828
static void
-
 
829
copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
-
 
830
{
-
 
831
    int y;
-
 
832
    int tmp, srcrowsize;
-
 
833
    int realwidth, realheight, realrowsize;
-
 
834
    int width = vport->width;
-
 
835
    int height = vport->height;
-
 
836
 
1148
 
-
 
1149
static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
-
 
1150
{
-
 
1151
    unsigned int width = vport->width;
-
 
1152
    unsigned int height = vport->height;
-
 
1153
   
837
    if (width + vport->x > screen.xres)
1154
    if (width + vport->x > screen.xres)
838
        width = screen.xres - vport->x;
1155
        width = screen.xres - vport->x;
839
    if (height + vport->y > screen.yres)
1156
    if (height + vport->y > screen.yres)
840
        height = screen.yres - vport->y;
1157
        height = screen.yres - vport->y;
841
   
1158
   
842
    realwidth = pmap->width <= width ? pmap->width : width;
1159
    unsigned int realwidth = pmap->width <= width ? pmap->width : width;
843
    realheight = pmap->height <= height ? pmap->height : height;
1160
    unsigned int realheight = pmap->height <= height ? pmap->height : height;
844
 
1161
   
845
    srcrowsize = vport->width * screen.pixelbytes;
1162
    unsigned int srcrowsize = vport->width * screen.pixelbytes;
846
    realrowsize = realwidth * screen.pixelbytes;
1163
    unsigned int realrowsize = realwidth * screen.pixelbytes;
847
   
1164
   
-
 
1165
    unsigned int y;
848
    for (y = 0; y < realheight; y++) {
1166
    for (y = 0; y < realheight; y++) {
849
        tmp = (vport->y + y) * screen.scanline +
1167
        unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
850
            vport->x * screen.pixelbytes;
-
 
851
        memcpy(pmap->data + srcrowsize * y, screen.fbaddress + tmp,
1168
        memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
852
            realrowsize);
-
 
853
    }
1169
    }
854
}
1170
}
855
 
1171
 
-
 
1172
 
856
/** Save viewport to pixmap */
1173
/** Save viewport to pixmap
-
 
1174
 *
857
static int
1175
 */
858
save_vp_to_pixmap(viewport_t *vport)
1176
static int save_vp_to_pixmap(viewport_t *vport)
859
{
1177
{
860
    int pm;
1178
    int pm;
861
    pixmap_t *pmap;
1179
    pixmap_t *pmap;
862
 
1180
   
863
    pm = find_free_pixmap();
1181
    pm = find_free_pixmap();
864
    if (pm == -1)
1182
    if (pm == -1)
865
        return ELIMIT;
1183
        return ELIMIT;
866
   
1184
   
867
    pmap = &pixmaps[pm];
1185
    pmap = &pixmaps[pm];
868
    pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
1186
    pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
869
    if (!pmap->data)
1187
    if (!pmap->data)
870
        return ENOMEM;
1188
        return ENOMEM;
871
 
1189
   
872
    pmap->width = vport->width;
1190
    pmap->width = vport->width;
873
    pmap->height = vport->height;
1191
    pmap->height = vport->height;
874
 
1192
   
875
    copy_vp_to_pixmap(vport, pmap);
1193
    copy_vp_to_pixmap(vport, pmap);
876
   
1194
   
877
    return pm;
1195
    return pm;
878
}
1196
}
879
 
1197
 
-
 
1198
 
880
/** Draw pixmap on screen
1199
/** Draw pixmap on screen
881
 *
1200
 *
882
 * @param vp Viewport to draw on
1201
 * @param vp Viewport to draw on
883
 * @param pm Pixmap identifier
1202
 * @param pm Pixmap identifier
-
 
1203
 *
884
 */
1204
 */
885
static int draw_pixmap(int vp, int pm)
1205
static int draw_pixmap(int vp, int pm)
886
{
1206
{
887
    pixmap_t *pmap = &pixmaps[pm];
1207
    pixmap_t *pmap = &pixmaps[pm];
888
    viewport_t *vport = &viewports[vp];
1208
    viewport_t *vport = &viewports[vp];
889
    int y;
1209
   
890
    int tmp, srcrowsize;
-
 
891
    int realwidth, realheight, realrowsize;
-
 
892
    int width = vport->width;
1210
    unsigned int width = vport->width;
893
    int height = vport->height;
1211
    unsigned int height = vport->height;
894
 
1212
   
895
    if (width + vport->x > screen.xres)
1213
    if (width + vport->x > screen.xres)
896
        width = screen.xres - vport->x;
1214
        width = screen.xres - vport->x;
897
    if (height + vport->y > screen.yres)
1215
    if (height + vport->y > screen.yres)
898
        height = screen.yres - vport->y;
1216
        height = screen.yres - vport->y;
899
 
1217
   
900
    if (!pmap->data)
1218
    if (!pmap->data)
901
        return EINVAL;
1219
        return EINVAL;
902
 
1220
   
903
    realwidth = pmap->width <= width ? pmap->width : width;
1221
    unsigned int realwidth = pmap->width <= width ? pmap->width : width;
904
    realheight = pmap->height <= height ? pmap->height : height;
1222
    unsigned int realheight = pmap->height <= height ? pmap->height : height;
905
 
1223
   
906
    srcrowsize = vport->width * screen.pixelbytes;
1224
    unsigned int srcrowsize = vport->width * screen.pixelbytes;
907
    realrowsize = realwidth * screen.pixelbytes;
1225
    unsigned int realrowsize = realwidth * screen.pixelbytes;
908
 
1226
   
-
 
1227
    unsigned int y;
909
    for (y = 0; y < realheight; y++) {
1228
    for (y = 0; y < realheight; y++) {
910
        tmp = (vport->y + y) * screen.scanline +
1229
        unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
911
            vport->x * screen.pixelbytes;
-
 
912
        memcpy(screen.fbaddress + tmp, pmap->data + y * srcrowsize,
1230
        memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
913
            realrowsize);
-
 
914
    }
1231
    }
-
 
1232
   
915
    return 0;
1233
    return EOK;
916
}
1234
}
917
 
1235
 
-
 
1236
 
918
/** Tick animation one step forward */
1237
/** Tick animation one step forward
-
 
1238
 *
919
static void
1239
 */
920
anims_tick(void)
1240
static void anims_tick(void)
921
{
1241
{
922
    int i;
1242
    unsigned int i;
923
    static int counts = 0;
1243
    static int counts = 0;
924
   
1244
   
925
    /* Limit redrawing */
1245
    /* Limit redrawing */
926
    counts = (counts + 1) % 8;
1246
    counts = (counts + 1) % 8;
927
    if (counts)
1247
    if (counts)
928
        return;
1248
        return;
929
 
1249
   
930
    for (i = 0; i < MAX_ANIMATIONS; i++) {
1250
    for (i = 0; i < MAX_ANIMATIONS; i++) {
931
        if (!animations[i].animlen || !animations[i].initialized ||
1251
        if ((!animations[i].animlen) || (!animations[i].initialized) ||
932
            !animations[i].enabled)
1252
            (!animations[i].enabled))
933
            continue;
1253
            continue;
934
        draw_pixmap(animations[i].vp,
1254
       
935
            animations[i].pixmaps[animations[i].pos]);
1255
        draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
936
        animations[i].pos = (animations[i].pos + 1) %
1256
        animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
937
            animations[i].animlen;
-
 
938
    }
1257
    }
939
}
1258
}
940
 
1259
 
941
 
1260
 
-
 
1261
static unsigned int pointer_x;
942
static int pointer_x, pointer_y;
1262
static unsigned int pointer_y;
943
static int pointer_shown, pointer_enabled;
1263
static bool pointer_shown, pointer_enabled;
944
static int pointer_vport = -1;
1264
static int pointer_vport = -1;
945
static int pointer_pixmap = -1;
1265
static int pointer_pixmap = -1;
946
 
1266
 
947
static void
1267
 
948
mouse_show(void)
1268
static void mouse_show(void)
949
{
1269
{
950
    int i, j;
1270
    int i, j;
951
    int visibility;
1271
    int visibility;
952
    int color;
1272
    int color;
953
    int bytepos;
1273
    int bytepos;
954
 
1274
   
955
    if (pointer_shown || !pointer_enabled)
1275
    if ((pointer_shown) || (!pointer_enabled))
956
        return;
1276
        return;
957
 
1277
   
958
    /* Save image under the cursor */
1278
    /* Save image under the pointer. */
959
    if (pointer_vport == -1) {
1279
    if (pointer_vport == -1) {
960
        pointer_vport = viewport_create(pointer_x, pointer_y,
1280
        pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height);
961
            pointer_width, pointer_height);
-
 
962
        if (pointer_vport < 0)
1281
        if (pointer_vport < 0)
963
            return;
1282
            return;
964
    } else {
1283
    } else {
965
        viewports[pointer_vport].x = pointer_x;
1284
        viewports[pointer_vport].x = pointer_x;
966
        viewports[pointer_vport].y = pointer_y;
1285
        viewports[pointer_vport].y = pointer_y;
967
    }
1286
    }
968
 
1287
   
969
    if (pointer_pixmap == -1)
1288
    if (pointer_pixmap == -1)
970
        pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
1289
        pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
971
    else
1290
    else
972
        copy_vp_to_pixmap(&viewports[pointer_vport],
1291
        copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
973
            &pixmaps[pointer_pixmap]);
-
 
974
 
1292
   
975
    /* Draw cursor */
1293
    /* Draw mouse pointer. */
976
    for (i = 0; i < pointer_height; i++)
1294
    for (i = 0; i < pointer_height; i++)
977
        for (j = 0; j < pointer_width; j++) {
1295
        for (j = 0; j < pointer_width; j++) {
978
            bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8;
1296
            bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8;
979
            visibility = pointer_mask_bits[bytepos] &
1297
            visibility = pointer_mask_bits[bytepos] &
980
                (1 << (j % 8));
1298
                (1 << (j % 8));
Line 988... Line 1306...
988
            }
1306
            }
989
        }
1307
        }
990
    pointer_shown = 1;
1308
    pointer_shown = 1;
991
}
1309
}
992
 
1310
 
993
static void
1311
 
994
mouse_hide(void)
1312
static void mouse_hide(void)
995
{
1313
{
996
    /* Restore image under the cursor */
1314
    /* Restore image under the pointer. */
997
    if (pointer_shown) {
1315
    if (pointer_shown) {
998
        draw_pixmap(pointer_vport, pointer_pixmap);
1316
        draw_pixmap(pointer_vport, pointer_pixmap);
999
        pointer_shown = 0;
1317
        pointer_shown = 0;
1000
    }
1318
    }
1001
}
1319
}
1002
 
1320
 
1003
static void
1321
 
1004
mouse_move(unsigned int x, unsigned int y)
1322
static void mouse_move(unsigned int x, unsigned int y)
1005
{
1323
{
1006
    mouse_hide();
1324
    mouse_hide();
1007
    pointer_x = x;
1325
    pointer_x = x;
1008
    pointer_y = y;
1326
    pointer_y = y;
1009
    mouse_show();
1327
    mouse_show();
1010
}
1328
}
1011
 
1329
 
1012
static int
1330
 
1013
anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
1331
static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
1014
{
1332
{
1015
    int handled = 1;
1333
    bool handled = true;
1016
    int retval = 0;
1334
    int retval = EOK;
1017
    int i,nvp;
1335
    int i, nvp;
1018
    int newval;
1336
    int newval;
1019
 
1337
   
1020
    switch (IPC_GET_METHOD(*call)) {
1338
    switch (IPC_GET_METHOD(*call)) {
1021
    case FB_ANIM_CREATE:
1339
    case FB_ANIM_CREATE:
1022
        nvp = IPC_GET_ARG1(*call);
1340
        nvp = IPC_GET_ARG1(*call);
1023
        if (nvp == -1)
1341
        if (nvp == -1)
1024
            nvp = vp;
1342
            nvp = vp;
Line 1104... Line 1422...
1104
    if (handled)
1422
    if (handled)
1105
        ipc_answer_0(callid, retval);
1423
        ipc_answer_0(callid, retval);
1106
    return handled;
1424
    return handled;
1107
}
1425
}
1108
 
1426
 
1109
/** Handler for messages concerning pixmap handling */
-
 
1110
static int
-
 
1111
pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
-
 
1112
{
-
 
1113
    int handled = 1;
-
 
1114
    int retval = 0;
-
 
1115
    int i,nvp;
-
 
1116
 
1427
 
-
 
1428
/** Handler for messages concerning pixmap handling
-
 
1429
 *
-
 
1430
 */
-
 
1431
static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
-
 
1432
{
-
 
1433
    bool handled = true;
-
 
1434
    int retval = EOK;
-
 
1435
    int i, nvp;
-
 
1436
   
1117
    switch (IPC_GET_METHOD(*call)) {
1437
    switch (IPC_GET_METHOD(*call)) {
1118
    case FB_VP_DRAW_PIXMAP:
1438
    case FB_VP_DRAW_PIXMAP:
1119
        nvp = IPC_GET_ARG1(*call);
1439
        nvp = IPC_GET_ARG1(*call);
1120
        if (nvp == -1)
1440
        if (nvp == -1)
1121
            nvp = vp;
1441
            nvp = vp;
Line 1149... Line 1469...
1149
        }
1469
        }
1150
        break;
1470
        break;
1151
    default:
1471
    default:
1152
        handled = 0;
1472
        handled = 0;
1153
    }
1473
    }
1154
 
1474
   
1155
    if (handled)
1475
    if (handled)
1156
        ipc_answer_0(callid, retval);
1476
        ipc_answer_0(callid, retval);
1157
    return handled;
1477
    return handled;
1158
   
1478
   
1159
}
1479
}
1160
 
1480
 
-
 
1481
static int rgb_from_style(attr_rgb_t *rgb, int style)
-
 
1482
{
-
 
1483
    switch (style) {
-
 
1484
    case STYLE_NORMAL:
-
 
1485
        rgb->fg_color = color_table[COLOR_BLACK];
-
 
1486
        rgb->bg_color = color_table[COLOR_WHITE];
-
 
1487
        break;
-
 
1488
    case STYLE_EMPHASIS:
-
 
1489
        rgb->fg_color = color_table[COLOR_RED];
-
 
1490
        rgb->bg_color = color_table[COLOR_WHITE];
-
 
1491
        break;
-
 
1492
    default:
-
 
1493
        return EINVAL;
-
 
1494
    }
-
 
1495
 
-
 
1496
    return EOK;
-
 
1497
}
-
 
1498
 
-
 
1499
static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color,
-
 
1500
    ipcarg_t bg_color, ipcarg_t flags)
-
 
1501
{
-
 
1502
    fg_color = (fg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);
-
 
1503
    bg_color = (bg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);
-
 
1504
 
-
 
1505
    rgb->fg_color = color_table[fg_color];
-
 
1506
    rgb->bg_color = color_table[bg_color];
-
 
1507
 
-
 
1508
    return EOK;
-
 
1509
}
-
 
1510
 
-
 
1511
static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a)
-
 
1512
{
-
 
1513
    int rc;
-
 
1514
 
-
 
1515
    switch (a->t) {
-
 
1516
    case at_style:
-
 
1517
        rc = rgb_from_style(rgb, a->a.s.style);
-
 
1518
        break;
-
 
1519
    case at_idx:
-
 
1520
        rc = rgb_from_idx(rgb, a->a.i.fg_color,
-
 
1521
            a->a.i.bg_color, a->a.i.flags);
-
 
1522
        break;
-
 
1523
    case at_rgb:
-
 
1524
        *rgb = a->a.r;
-
 
1525
        rc = EOK;
-
 
1526
        break;
-
 
1527
    }
-
 
1528
 
-
 
1529
    return rc;
-
 
1530
}
-
 
1531
 
-
 
1532
static int fb_set_style(viewport_t *vport, ipcarg_t style)
-
 
1533
{
-
 
1534
    return rgb_from_style(&vport->attr, (int) style);
-
 
1535
}
-
 
1536
 
-
 
1537
static int fb_set_color(viewport_t *vport, ipcarg_t fg_color,
-
 
1538
    ipcarg_t bg_color, ipcarg_t flags)
-
 
1539
{
-
 
1540
    return rgb_from_idx(&vport->attr, fg_color, bg_color, flags);
-
 
1541
}
-
 
1542
 
1161
/** Function for handling connections to FB
1543
/** Function for handling connections to FB
1162
 *
1544
 *
1163
 */
1545
 */
1164
static void
-
 
1165
fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
1546
static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
1166
{
1547
{
1167
    ipc_callid_t callid;
-
 
1168
    ipc_call_t call;
-
 
1169
    int retval;
-
 
1170
    int i;
-
 
1171
    unsigned int row,col;
1548
    unsigned int vp = 0;
1172
    char c;
-
 
1173
 
-
 
1174
    int vp = 0;
-
 
1175
    viewport_t *vport = &viewports[0];
1549
    viewport_t *vport = &viewports[vp];
1176
 
1550
   
1177
    if (client_connected) {
1551
    if (client_connected) {
1178
        ipc_answer_0(iid, ELIMIT);
1552
        ipc_answer_0(iid, ELIMIT);
1179
        return;
1553
        return;
1180
    }
1554
    }
-
 
1555
   
-
 
1556
    /* Accept connection */
1181
    client_connected = 1;
1557
    client_connected = true;
1182
    ipc_answer_0(iid, EOK); /* Accept connection */
1558
    ipc_answer_0(iid, EOK);
1183
 
1559
   
1184
    while (1) {
1560
    while (true) {
-
 
1561
        ipc_callid_t callid;
-
 
1562
        ipc_call_t call;
-
 
1563
        int retval;
-
 
1564
        unsigned int i;
-
 
1565
        int scroll;
-
 
1566
        wchar_t ch;
-
 
1567
        unsigned int row, col;
-
 
1568
       
1185
        if (vport->cursor_active || anims_enabled)
1569
        if ((vport->cursor_active) || (anims_enabled))
1186
            callid = async_get_call_timeout(&call, 250000);
1570
            callid = async_get_call_timeout(&call, 250000);
1187
        else
1571
        else
1188
            callid = async_get_call(&call);
1572
            callid = async_get_call(&call);
1189
 
1573
       
1190
        mouse_hide();
1574
        mouse_hide();
1191
        if (!callid) {
1575
        if (!callid) {
1192
            cursor_blink(vport);
1576
            cursor_blink(vport);
1193
            anims_tick();
1577
            anims_tick();
1194
            mouse_show();
1578
            mouse_show();
1195
            continue;
1579
            continue;
1196
        }
1580
        }
-
 
1581
       
1197
        if (shm_handle(callid, &call, vp))
1582
        if (shm_handle(callid, &call, vp))
1198
            continue;
1583
            continue;
-
 
1584
       
1199
        if (pixmap_handle(callid, &call, vp))
1585
        if (pixmap_handle(callid, &call, vp))
1200
            continue;
1586
            continue;
-
 
1587
       
1201
        if (anim_handle(callid, &call, vp))
1588
        if (anim_handle(callid, &call, vp))
1202
            continue;
1589
            continue;
1203
 
1590
       
1204
        switch (IPC_GET_METHOD(call)) {
1591
        switch (IPC_GET_METHOD(call)) {
1205
        case IPC_M_PHONE_HUNGUP:
1592
        case IPC_M_PHONE_HUNGUP:
1206
            client_connected = 0;
1593
            client_connected = false;
-
 
1594
           
1207
            /* cleanup other viewports */
1595
            /* Cleanup other viewports */
1208
            for (i = 1; i < MAX_VIEWPORTS; i++)
1596
            for (i = 1; i < MAX_VIEWPORTS; i++)
1209
                vport->initialized = 0;
1597
                vport->initialized = false;
-
 
1598
           
1210
            return; /* Exit thread */
1599
            /* Exit thread */
-
 
1600
            return;
1211
 
1601
       
1212
        case FB_PUTCHAR:
1602
        case FB_PUTCHAR:
1213
        case FB_TRANS_PUTCHAR:
-
 
1214
            c = IPC_GET_ARG1(call);
1603
            ch = IPC_GET_ARG1(call);
1215
            row = IPC_GET_ARG2(call);
1604
            row = IPC_GET_ARG2(call);
1216
            col = IPC_GET_ARG3(call);
1605
            col = IPC_GET_ARG3(call);
-
 
1606
           
1217
            if (row >= vport->rows || col >= vport->cols) {
1607
            if ((col >= vport->cols) || (row >= vport->rows)) {
1218
                retval = EINVAL;
1608
                retval = EINVAL;
1219
                break;
1609
                break;
1220
            }
1610
            }
1221
            ipc_answer_0(callid, EOK);
1611
            ipc_answer_0(callid, EOK);
1222
 
1612
           
1223
            draw_char(vport, c, row, col, vport->style,
1613
            draw_char(vport, ch, col, row);
-
 
1614
           
1224
                IPC_GET_METHOD(call) == FB_TRANS_PUTCHAR);
1615
            /* Message already answered */
1225
            continue; /* msg already answered */
1616
            continue;
1226
        case FB_CLEAR:
1617
        case FB_CLEAR:
1227
            clear_port(vport);
1618
            vport_clear(vport);
1228
            cursor_print(vport);
1619
            cursor_show(vport);
1229
            retval = 0;
1620
            retval = EOK;
1230
            break;
1621
            break;
1231
        case FB_CURSOR_GOTO:
1622
        case FB_CURSOR_GOTO:
1232
            row = IPC_GET_ARG1(call);
1623
            row = IPC_GET_ARG1(call);
1233
            col = IPC_GET_ARG2(call);
1624
            col = IPC_GET_ARG2(call);
-
 
1625
           
1234
            if (row >= vport->rows || col >= vport->cols) {
1626
            if ((col >= vport->cols) || (row >= vport->rows)) {
1235
                retval = EINVAL;
1627
                retval = EINVAL;
1236
                break;
1628
                break;
1237
            }
1629
            }
1238
            retval = 0;
1630
            retval = EOK;
-
 
1631
           
1239
            cursor_hide(vport);
1632
            cursor_hide(vport);
1240
            vport->cur_col = col;
1633
            vport->cur_col = col;
1241
            vport->cur_row = row;
1634
            vport->cur_row = row;
1242
            cursor_print(vport);
1635
            cursor_show(vport);
1243
            break;
1636
            break;
1244
        case FB_CURSOR_VISIBILITY:
1637
        case FB_CURSOR_VISIBILITY:
1245
            cursor_hide(vport);
1638
            cursor_hide(vport);
1246
            vport->cursor_active = IPC_GET_ARG1(call);
1639
            vport->cursor_active = IPC_GET_ARG1(call);
1247
            cursor_print(vport);
1640
            cursor_show(vport);
1248
            retval = 0;
1641
            retval = EOK;
1249
            break;
1642
            break;
1250
        case FB_GET_CSIZE:
1643
        case FB_GET_CSIZE:
1251
            ipc_answer_2(callid, EOK, vport->rows, vport->cols);
1644
            ipc_answer_2(callid, EOK, vport->rows, vport->cols);
1252
            continue;
1645
            continue;
1253
        case FB_SCROLL:
1646
        case FB_SCROLL:
1254
            i = IPC_GET_ARG1(call);
1647
            scroll = IPC_GET_ARG1(call);
1255
            if (i > vport->rows || i < (- (int)vport->rows)) {
1648
            if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) {
1256
                retval = EINVAL;
1649
                retval = EINVAL;
1257
                break;
1650
                break;
1258
            }
1651
            }
1259
            cursor_hide(vport);
1652
            cursor_hide(vport);
1260
            scroll_port(vport, i*FONT_SCANLINES);
1653
            vport_scroll(vport, scroll);
1261
            cursor_print(vport);
1654
            cursor_show(vport);
1262
            retval = 0;
-
 
1263
            break;
-
 
1264
        case FB_VIEWPORT_DB:
-
 
1265
            /* Enable double buffering */
-
 
1266
            i = IPC_GET_ARG1(call);
-
 
1267
            if (i == -1)
-
 
1268
                i = vp;
-
 
1269
            if (i < 0 || i >= MAX_VIEWPORTS) {
-
 
1270
                retval = EINVAL;
-
 
1271
                break;
-
 
1272
            }
-
 
1273
            if (!viewports[i].initialized ) {
-
 
1274
                retval = EADDRNOTAVAIL;
-
 
1275
                break;
-
 
1276
            }
-
 
1277
            viewports[i].dboffset = 0;
-
 
1278
            if (IPC_GET_ARG2(call) == 1 && !viewports[i].dbdata)
-
 
1279
                viewports[i].dbdata =
-
 
1280
                    malloc(screen.pixelbytes *
-
 
1281
                    viewports[i].width * viewports[i].height);
-
 
1282
            else if (IPC_GET_ARG2(call) == 0 &&
-
 
1283
                viewports[i].dbdata) {
-
 
1284
                free(viewports[i].dbdata);
-
 
1285
                viewports[i].dbdata = NULL;
-
 
1286
            }
-
 
1287
            retval = 0;
1655
            retval = EOK;
1288
            break;
1656
            break;
1289
        case FB_VIEWPORT_SWITCH:
1657
        case FB_VIEWPORT_SWITCH:
1290
            i = IPC_GET_ARG1(call);
1658
            i = IPC_GET_ARG1(call);
1291
            if (i < 0 || i >= MAX_VIEWPORTS) {
1659
            if (i >= MAX_VIEWPORTS) {
1292
                retval = EINVAL;
1660
                retval = EINVAL;
1293
                break;
1661
                break;
1294
            }
1662
            }
1295
            if (! viewports[i].initialized ) {
1663
            if (!viewports[i].initialized) {
1296
                retval = EADDRNOTAVAIL;
1664
                retval = EADDRNOTAVAIL;
1297
                break;
1665
                break;
1298
            }
1666
            }
1299
            cursor_hide(vport);
1667
            cursor_hide(vport);
1300
            vp = i;
1668
            vp = i;
1301
            vport = &viewports[vp];
1669
            vport = &viewports[vp];
1302
            cursor_print(vport);
1670
            cursor_show(vport);
1303
            retval = 0;
1671
            retval = EOK;
1304
            break;
1672
            break;
1305
        case FB_VIEWPORT_CREATE:
1673
        case FB_VIEWPORT_CREATE:
1306
            retval = viewport_create(IPC_GET_ARG1(call) >> 16,
1674
            retval = vport_create(IPC_GET_ARG1(call) >> 16,
1307
                IPC_GET_ARG1(call) & 0xffff,
1675
                IPC_GET_ARG1(call) & 0xffff,
1308
                IPC_GET_ARG2(call) >> 16,
1676
                IPC_GET_ARG2(call) >> 16,
1309
                IPC_GET_ARG2(call) & 0xffff);
1677
                IPC_GET_ARG2(call) & 0xffff);
1310
            break;
1678
            break;
1311
        case FB_VIEWPORT_DELETE:
1679
        case FB_VIEWPORT_DELETE:
1312
            i = IPC_GET_ARG1(call);
1680
            i = IPC_GET_ARG1(call);
1313
            if (i < 0 || i >= MAX_VIEWPORTS) {
1681
            if (i >= MAX_VIEWPORTS) {
1314
                retval = EINVAL;
1682
                retval = EINVAL;
1315
                break;
1683
                break;
1316
            }
1684
            }
1317
            if (! viewports[i].initialized ) {
1685
            if (!viewports[i].initialized) {
1318
                retval = EADDRNOTAVAIL;
1686
                retval = EADDRNOTAVAIL;
1319
                break;
1687
                break;
1320
            }
1688
            }
1321
            viewports[i].initialized = 0;
1689
            viewports[i].initialized = false;
1322
            if (viewports[i].dbdata) {
1690
            if (viewports[i].bgpixel)
1323
                free(viewports[i].dbdata);
1691
                free(viewports[i].bgpixel);
1324
                viewports[i].dbdata = NULL;
1692
            if (viewports[i].backbuf)
1325
            }
1693
                free(viewports[i].backbuf);
1326
            retval = 0;
1694
            retval = EOK;
1327
            break;
1695
            break;
1328
        case FB_SET_STYLE:
1696
        case FB_SET_STYLE:
-
 
1697
            retval = fb_set_style(vport, IPC_GET_ARG1(call));
-
 
1698
            break;
-
 
1699
        case FB_SET_COLOR:
-
 
1700
            retval = fb_set_color(vport, IPC_GET_ARG1(call),
-
 
1701
                IPC_GET_ARG2(call), IPC_GET_ARG3(call));
-
 
1702
            break;
-
 
1703
        case FB_SET_RGB_COLOR:
1329
            vport->style.fg_color = IPC_GET_ARG1(call);
1704
            vport->attr.fg_color = IPC_GET_ARG1(call);
1330
            vport->style.bg_color = IPC_GET_ARG2(call);
1705
            vport->attr.bg_color = IPC_GET_ARG2(call);
1331
            retval = 0;
1706
            retval = EOK;
1332
            break;
1707
            break;
1333
        case FB_GET_RESOLUTION:
1708
        case FB_GET_RESOLUTION:
1334
            ipc_answer_2(callid, EOK, screen.xres, screen.yres);
1709
            ipc_answer_2(callid, EOK, screen.xres, screen.yres);
1335
            continue;
1710
            continue;
1336
        case FB_POINTER_MOVE:
1711
        case FB_POINTER_MOVE:
1337
            pointer_enabled = 1;
1712
            pointer_enabled = true;
1338
            mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
1713
            mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
1339
            retval = 0;
1714
            retval = EOK;
-
 
1715
            break;
-
 
1716
        case FB_SCREEN_YIELD:
-
 
1717
        case FB_SCREEN_RECLAIM:
-
 
1718
            retval = EOK;
1340
            break;
1719
            break;
1341
        default:
1720
        default:
1342
            retval = ENOENT;
1721
            retval = ENOENT;
1343
        }
1722
        }
1344
        ipc_answer_0(callid, retval);
1723
        ipc_answer_0(callid, retval);
1345
    }
1724
    }
1346
}
1725
}
1347
 
1726
 
1348
/** Initialization of framebuffer */
1727
/** Initialization of framebuffer
-
 
1728
 *
1349
int
1729
 */
1350
fb_init(void)
1730
int fb_init(void)
1351
{
1731
{
1352
    void *fb_ph_addr;
-
 
1353
    unsigned int fb_width;
-
 
1354
    unsigned int fb_height;
-
 
1355
    unsigned int fb_scanline;
-
 
1356
    unsigned int fb_visual;
-
 
1357
    unsigned int fb_offset;
-
 
1358
    bool fb_invert_colors;
-
 
1359
    void *fb_addr;
-
 
1360
    size_t asz;
-
 
1361
 
-
 
1362
    async_set_client_connection(fb_client_connection);
1732
    async_set_client_connection(fb_client_connection);
1363
 
-
 
1364
    fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
-
 
1365
    fb_offset = sysinfo_value("fb.offset");
-
 
1366
    fb_width = sysinfo_value("fb.width");
-
 
1367
    fb_height = sysinfo_value("fb.height");
-
 
1368
    fb_scanline = sysinfo_value("fb.scanline");
-
 
1369
    fb_visual = sysinfo_value("fb.visual");
-
 
1370
    fb_invert_colors = sysinfo_value("fb.invert-colors");
-
 
1371
 
-
 
1372
    asz = fb_scanline * fb_height;
-
 
1373
    fb_addr = as_get_mappable_page(asz);
-
 
1374
   
1733
   
-
 
1734
    void *fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
-
 
1735
    unsigned int fb_offset = sysinfo_value("fb.offset");
-
 
1736
    unsigned int fb_width = sysinfo_value("fb.width");
-
 
1737
    unsigned int fb_height = sysinfo_value("fb.height");
-
 
1738
    unsigned int fb_scanline = sysinfo_value("fb.scanline");
-
 
1739
    unsigned int fb_visual = sysinfo_value("fb.visual");
-
 
1740
   
-
 
1741
    unsigned int fbsize = fb_scanline * fb_height;
-
 
1742
    void *fb_addr = as_get_mappable_page(fbsize);
-
 
1743
   
1375
    physmem_map(fb_ph_addr + fb_offset, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >>
1744
    if (physmem_map(fb_ph_addr + fb_offset, fb_addr,
1376
        PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
1745
        ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
-
 
1746
        return -1;
1377
 
1747
   
1378
    if (screen_init(fb_addr, fb_offset, fb_width, fb_height, fb_scanline, fb_visual,
1748
    if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual))
1379
        fb_invert_colors))
-
 
1380
        return 0;
1749
        return 0;
1381
   
1750
   
1382
    return -1;
1751
    return -1;
1383
}
1752
}
1384
 
1753
 
1385
/**
1754
/**
1386
 * @}
1755
 * @}
1387
 */
1756
 */