source: mainline/console/gcons.c@ 6d5005c

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

Console graphics update.
Slight speed improvement on console redraw.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
2 * Copyright (C) 2006 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <ipc/fb.h>
30#include <ipc/ipc.h>
31#include <async.h>
32#include <stdio.h>
33#include <sys/mman.h>
34#include <string.h>
35#include <align.h>
36
37#include "console.h"
38#include "gcons.h"
39
40#define CONSOLE_TOP 65
41#define CONSOLE_MARGIN 6
42
43#define STATUS_START 110
44#define STATUS_TOP 8
45#define STATUS_SPACE 3
46#define STATUS_WIDTH 48
47#define STATUS_HEIGHT 48
48
49#define MAIN_COLOR 0xffffff
50
51static int use_gcons = 0;
52static ipcarg_t xres,yres;
53
54enum butstate {
55 CONS_DISCONNECTED = 0,
56 CONS_SELECTED,
57 CONS_IDLE,
58 CONS_HAS_DATA,
59 CONS_KERNEL,
60 CONS_DISCONNECTED_SEL,
61 CONS_LAST
62};
63
64static int console_vp;
65static int cstatus_vp[CONSOLE_COUNT];
66static int cstat_row, cstat_col; /* Size of cstatus buttons */
67static enum butstate console_state[CONSOLE_COUNT];
68
69static int fbphone;
70
71/** List of pixmaps identifying these icons */
72static int ic_pixmaps[CONS_LAST] = {-1,-1,-1,-1,-1,-1};
73
74static int active_console = 0;
75
76static void vp_switch(int vp)
77{
78 nsend_call(fbphone,FB_VIEWPORT_SWITCH, vp);
79}
80
81/** Create view port */
82static int vp_create(unsigned int x, unsigned int y,
83 unsigned int width, unsigned int height)
84{
85 /* Init function, use ipc_call_sync */
86 return ipc_call_sync_2(fbphone, FB_VIEWPORT_CREATE,
87 (x << 16) | y, (width << 16) | height,
88 NULL, NULL);
89}
90
91static void clear(void)
92{
93 nsend_call(fbphone, FB_CLEAR, 0);
94
95}
96
97static void set_style(int fgcolor, int bgcolor)
98{
99 nsend_call_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor);
100}
101
102/** Transparent putchar */
103static void tran_putch(char c, int row, int col)
104{
105 nsend_call_3(fbphone, FB_TRANS_PUTCHAR, c, row, col);
106}
107
108/** Redraw the button showing state of a given console */
109static void redraw_state(int consnum)
110{
111 char data[5];
112 int i;
113 enum butstate state = console_state[consnum];
114
115 vp_switch(cstatus_vp[consnum]);
116 if (ic_pixmaps[state] != -1)
117 nsend_call_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[consnum], ic_pixmaps[state]);
118
119 if (state != CONS_DISCONNECTED && state != CONS_KERNEL && state != CONS_DISCONNECTED_SEL) {
120 snprintf(data, 5, "%d", consnum+1);
121 for (i=0;data[i];i++)
122 tran_putch(data[i], 1, 2+i);
123 }
124}
125
126/** Notification run on changing console (except kernel console) */
127void gcons_change_console(int consnum)
128{
129 int i;
130
131 if (!use_gcons)
132 return;
133
134 if (active_console == KERNEL_CONSOLE) {
135 for (i=0; i < CONSOLE_COUNT; i++)
136 redraw_state(i);
137 } else {
138 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
139 console_state[active_console] = CONS_DISCONNECTED;
140 else
141 console_state[active_console] = CONS_IDLE;
142 redraw_state(active_console);
143 }
144 active_console = consnum;
145
146 if (console_state[consnum] == CONS_DISCONNECTED) {
147 console_state[consnum] = CONS_DISCONNECTED_SEL;
148 redraw_state(consnum);
149 } else
150 console_state[consnum] = CONS_SELECTED;
151 redraw_state(consnum);
152
153 vp_switch(console_vp);
154}
155
156/** Notification function that gets called on new output to virtual console */
157void gcons_notify_char(int consnum)
158{
159 if (!use_gcons)
160 return;
161
162 if (consnum == active_console || console_state[consnum] == CONS_HAS_DATA)
163 return;
164
165 console_state[consnum] = CONS_HAS_DATA;
166
167 if (active_console == KERNEL_CONSOLE)
168 return;
169
170 redraw_state(consnum);
171
172 vp_switch(console_vp);
173}
174
175/** Notification function called on console connect */
176void gcons_notify_connect(int consnum)
177{
178 if (!use_gcons)
179 return;
180 if (active_console == consnum)
181 console_state[consnum] = CONS_SELECTED;
182 else
183 console_state[consnum] = CONS_IDLE;
184
185 if (active_console == KERNEL_CONSOLE)
186 return;
187
188 redraw_state(consnum);
189 vp_switch(console_vp);
190}
191
192/** Change to kernel console */
193void gcons_in_kernel(void)
194{
195 if (console_state[active_console] == CONS_DISCONNECTED_SEL)
196 console_state[active_console] = CONS_DISCONNECTED;
197 else
198 console_state[active_console] = CONS_IDLE;
199 redraw_state(active_console);
200
201 active_console = KERNEL_CONSOLE; /* Set to kernel console */
202 vp_switch(0);
203}
204
205/** Draw a PPM pixmap to framebuffer
206 *
207 * @param logo Pointer to PPM data
208 * @param size Size of PPM data
209 * @param x Coordinate of upper left corner
210 * @param y Coordinate of upper left corner
211 */
212static void draw_pixmap(char *logo, size_t size, int x, int y)
213{
214 char *shm;
215 int rc;
216
217 /* Create area */
218 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
219 if (shm == MAP_FAILED)
220 return;
221
222 memcpy(shm, logo, size);
223 /* Send area */
224 rc = sync_send_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
225 if (rc)
226 goto exit;
227 rc = sync_send_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
228 if (rc)
229 goto drop;
230 /* Draw logo */
231 nsend_call_2(fbphone, FB_DRAW_PPM, x, y);
232drop:
233 /* Drop area */
234 nsend_call(fbphone, FB_DROP_SHM, 0);
235exit:
236 /* Remove area */
237 munmap(shm, size);
238}
239
240extern char _binary_helenos_ppm_start[0];
241extern int _binary_helenos_ppm_size;
242extern char _binary_nameic_ppm_start[0];
243extern int _binary_nameic_ppm_size;
244/** Redraws console graphics */
245static void gcons_redraw_console(void)
246{
247 int i;
248 size_t hsize = (size_t)&_binary_helenos_ppm_size;
249
250 if (!use_gcons)
251 return;
252
253 vp_switch(0);
254 set_style(MAIN_COLOR, MAIN_COLOR);
255 clear();
256 draw_pixmap(_binary_helenos_ppm_start, (size_t)&_binary_helenos_ppm_size, xres-66, 2);
257 draw_pixmap(_binary_nameic_ppm_start, (size_t)&_binary_nameic_ppm_size, 5, 17);
258
259 for (i=0;i < CONSOLE_COUNT; i++)
260 redraw_state(i);
261 vp_switch(console_vp);
262}
263
264/** Creates a pixmap on framebuffer
265 *
266 * @param data PPM data
267 * @param size PPM data size
268 * @return Pixmap identification
269 */
270static int make_pixmap(char *data, int size)
271{
272 char *shm;
273 int rc;
274 int pxid = -1;
275
276 /* Create area */
277 shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
278 if (shm == MAP_FAILED)
279 return -1;
280
281 memcpy(shm, data, size);
282 /* Send area */
283 rc = sync_send_2(fbphone, FB_PREPARE_SHM, (ipcarg_t)shm, 0, NULL, NULL);
284 if (rc)
285 goto exit;
286 rc = sync_send_3(fbphone, IPC_M_AS_AREA_SEND, (ipcarg_t)shm, 0, PROTO_READ, NULL, NULL, NULL);
287 if (rc)
288 goto drop;
289
290 /* Obtain pixmap */
291 rc = sync_send(fbphone, FB_SHM2PIXMAP, 0, NULL);
292 if (rc < 0)
293 goto drop;
294 pxid = rc;
295drop:
296 /* Drop area */
297 nsend_call(fbphone, FB_DROP_SHM, 0);
298exit:
299 /* Remove area */
300 munmap(shm, size);
301
302 return pxid;
303}
304
305extern char _binary_cons_selected_ppm_start[0];
306extern int _binary_cons_selected_ppm_size;
307extern char _binary_cons_idle_ppm_start[0];
308extern int _binary_cons_idle_ppm_size;
309extern char _binary_cons_has_data_ppm_start[0];
310extern int _binary_cons_has_data_ppm_size;
311extern char _binary_cons_kernel_ppm_start[0];
312extern int _binary_cons_kernel_ppm_size;
313/** Initialize nice graphical console environment */
314void gcons_init(int phone)
315{
316 int rc;
317 int i;
318
319 fbphone = phone;
320
321 rc = ipc_call_sync_2(phone, FB_GET_RESOLUTION, 0, 0, &xres, &yres);
322 if (rc)
323 return;
324
325 if (xres < 800 || yres < 600)
326 return;
327
328 /* create console viewport */
329 /* Align width & height to character size */
330 console_vp = vp_create(CONSOLE_MARGIN, CONSOLE_TOP,
331 ALIGN_DOWN(xres-2*CONSOLE_MARGIN, 8),
332 ALIGN_DOWN(yres-(CONSOLE_TOP+CONSOLE_MARGIN),16));
333 if (console_vp < 0)
334 return;
335
336 /* Create status buttons */
337 for (i=0; i < CONSOLE_COUNT; i++) {
338 cstatus_vp[i] = vp_create(STATUS_START+CONSOLE_MARGIN+i*(STATUS_WIDTH+STATUS_SPACE),
339 STATUS_TOP, STATUS_WIDTH, STATUS_HEIGHT);
340 if (cstatus_vp[i] < 0)
341 return;
342 vp_switch(cstatus_vp[i]);
343 set_style(0x202020, 0xffffff);
344 }
345
346 /* Initialize icons */
347 ic_pixmaps[CONS_SELECTED] = make_pixmap(_binary_cons_selected_ppm_start,
348 (int)&_binary_cons_selected_ppm_size);
349 ic_pixmaps[CONS_IDLE] = make_pixmap(_binary_cons_idle_ppm_start,
350 (int)&_binary_cons_idle_ppm_size);
351 ic_pixmaps[CONS_HAS_DATA] = make_pixmap(_binary_cons_has_data_ppm_start,
352 (int)&_binary_cons_has_data_ppm_size);
353 ic_pixmaps[CONS_DISCONNECTED] = make_pixmap(_binary_cons_idle_ppm_start,
354 (int)&_binary_cons_idle_ppm_size);
355 ic_pixmaps[CONS_KERNEL] = make_pixmap(_binary_cons_kernel_ppm_start,
356 (int)&_binary_cons_kernel_ppm_size);
357 ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
358
359 use_gcons = 1;
360 console_state[0] = CONS_DISCONNECTED_SEL;
361 console_state[KERNEL_CONSOLE] = CONS_KERNEL;
362 gcons_redraw_console();
363}
Note: See TracBrowser for help on using the repository browser.