Mercurial > hg > Game > Cerium
comparison Renderer/Engine/ps3fb/cp_vt.cc @ 981:fdb36a9c5030 draft
add double buffering frame device
author | root@henri.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Thu, 30 Sep 2010 23:54:08 +0900 |
parents | |
children | 9f5e6bfb1c09 |
comparison
equal
deleted
inserted
replaced
980:a788a82767ea | 981:fdb36a9c5030 |
---|---|
1 // cp_vt.c | |
2 // | |
3 // Copyright (c) 2006, Mike Acton <macton@cellperformance.com> | |
4 // | |
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | |
6 // documentation files (the "Software"), to deal in the Software without restriction, including without | |
7 // limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
8 // the Software, and to permit persons to whom the Software is furnished to do so, subject to the following | |
9 // conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in all copies or substantial | |
12 // portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT | |
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO | |
16 // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
17 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE | |
18 // OR OTHER DEALINGS IN THE SOFTWARE. | |
19 | |
20 // NOTES: | |
21 // From http://www.linuxjournal.com/article/2597 | |
22 // | |
23 // "Console ttys are used when the keyboard and monitor are directly connected to the system without running | |
24 // the X Window System. Since you can have several virtual consoles, the devices are tty0 through tty63. In | |
25 // theory you can have 64 virtual consoles, but most people use only a few. The device /dev/console is | |
26 // identical to tty0 and is needed for historical reasons. If your system lets you log in on consoles 1 | |
27 // through 6, then when you run X Windows System, X uses console 7, so you'll need /dev/tty1 through /dev/ | |
28 // tty7 on your system. I recommend having files up through /dev/tty12. For more information on using | |
29 // virtual consoles, see the article Keyboards, Consoles and VT Cruising by John Fisk in the November 1996 | |
30 // issue of Linux Journal" | |
31 | |
32 #include <stdio.h> | |
33 #include <stdint.h> | |
34 #include <fcntl.h> | |
35 #include <unistd.h> | |
36 #include <sys/ioctl.h> | |
37 #include <linux/vt.h> | |
38 #include <linux/kd.h> | |
39 #include "cp_vt.h" | |
40 | |
41 | |
42 static inline const char* | |
43 select_error_str( int existing_error, const char* const existing_error_str, int new_error, const char* const new_error_str ) | |
44 { | |
45 // Only report the first error found - any error that follows is probably just a cascading effect. | |
46 const char* error_str = (char*)( (~(intptr_t)existing_error & (intptr_t)new_error & (intptr_t)new_error_str) | |
47 | ((intptr_t)existing_error & (intptr_t)existing_error_str) ); | |
48 | |
49 return (error_str); | |
50 } | |
51 | |
52 | |
53 int | |
54 cp_vt_open_graphics(cp_vt* restrict vt) | |
55 { | |
56 const char* error_str = NULL; | |
57 int error = 0; | |
58 | |
59 // Open the current tty | |
60 | |
61 // From http://tldp.org/HOWTO/Text-Terminal-HOWTO-6.html#ss6.3 | |
62 // (An excellent overview by David S. Lawyer) | |
63 // | |
64 // "In Linux the PC monitor is usually called the console and has several device special files associated | |
65 // with it: vc/0 (tty0), vc/1 (tty1), vc/2 (tty2), etc. When you log in you are on vc/1. To go to vc/2 | |
66 // (on the same screen) press down the 2 keys Alt(left)-F3. For vc/3 use Left Alt-F3, etc. These (vc/1, | |
67 // vc/2, vc/3, etc.) are called "virtual terminals". vc/0 (tty0) is just an alias for the current virtual | |
68 // terminal and it's where messages from the system are sent. Thus messages from the system will be seen | |
69 // on the console (monitor) regardless of which virtual terminal it is displaying." | |
70 | |
71 const int cur_tty = open( "/dev/tty0", O_RDWR ); | |
72 const int open_cur_tty_error = (cur_tty >> ((sizeof(int)*8)-1)); | |
73 const char* open_cur_tty_error_str = "Could not open /dev/tty0. Check permissions."; | |
74 | |
75 error_str = select_error_str( error, error_str, open_cur_tty_error, open_cur_tty_error_str ); | |
76 error = error | open_cur_tty_error; | |
77 | |
78 // From: http://www.linuxjournal.com/article/2783 | |
79 // (A little out of date, but a nice primer.) | |
80 // | |
81 // "VT_GETSTATE returns the state of all VT's in the kernel in the structure: | |
82 // | |
83 // struct vt_stat { | |
84 // ushort v_active; | |
85 // ushort v_signal; | |
86 // ushort v_state; | |
87 // }; | |
88 // | |
89 // v_active the currently active VT | |
90 // v_state mask of all the opened VT's | |
91 // | |
92 // v_active holds the number of the active VT (starting from 1), while v_state | |
93 // holds a mask where there is a 1 for each VT that has been opened by some process. | |
94 // Note that VT 0 is always opened in this scenario, since it refers to the current VT. | |
95 // | |
96 // Bugs: | |
97 // The v_signal member is unsupported." | |
98 | |
99 struct vt_stat vts; | |
100 | |
101 const int get_state_error = ioctl( cur_tty, VT_GETSTATE, &vts ); | |
102 const char* get_state_error_str = "VT_GETSTATE failed on /dev/tty0"; | |
103 | |
104 error_str = select_error_str( error, error_str, get_state_error, get_state_error_str ); | |
105 error = error | get_state_error; | |
106 | |
107 vt->prev_tty_ndx = vts.v_active; | |
108 | |
109 // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt | |
110 // (Close enough to Linux and a pretty good source of documentation.) | |
111 // | |
112 // "VT_OPENQRY | |
113 // This call is used to find an available VT. The argu- | |
114 // ment to the ioctl is a pointer to an integer. The integer | |
115 // will be filled in with the number of the first avail- | |
116 // able VT that no other process has open (and hence, is | |
117 // available to be opened). If there are no available | |
118 // VTs, then -1 will be filled in." | |
119 | |
120 const int open_query_error = ioctl( cur_tty, VT_OPENQRY, &vt->tty_ndx); | |
121 const char* open_query_error_str = "No open ttys available"; | |
122 | |
123 error_str = select_error_str( error, error_str, open_query_error, open_query_error_str ); | |
124 error = error | open_query_error; | |
125 | |
126 const int close_cur_tty_error = close( cur_tty ); | |
127 const char* close_cur_tty_error_str = "Could not close parent tty"; | |
128 | |
129 error_str = select_error_str( error, error_str, close_cur_tty_error, close_cur_tty_error_str ); | |
130 error = error | close_cur_tty_error; | |
131 | |
132 char tty_file_name[11]; | |
133 | |
134 (void)snprintf( tty_file_name, 11, "/dev/tty%d", vt->tty_ndx ); | |
135 | |
136 const int tty = open( tty_file_name, O_RDWR ); | |
137 const int open_tty_error = (cur_tty >> ((sizeof(int)*8)-1)); | |
138 const char* open_tty_error_str = "Could not open tty"; | |
139 | |
140 error_str = select_error_str( error, error_str, open_tty_error, open_tty_error_str ); | |
141 error = error | open_tty_error; | |
142 | |
143 vt->tty = tty; | |
144 | |
145 // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt | |
146 // (Close enough to Linux and a pretty good source of documentation.) | |
147 // | |
148 // "VT_ACTIVATE | |
149 // This call has the effect of making the VT specified in | |
150 // the argument the active VT. The VT manager will cause | |
151 // a switch to occur in the same manner as if a hotkey had | |
152 // initiated the switch. If the specified VT is not open | |
153 // or does not exist the call will fail and errno will be | |
154 // set to ENXIO." | |
155 // | |
156 // "VT_WAITACTIVE | |
157 // If the specified VT is already active, this call | |
158 // returns immediately. Otherwise, it will sleep until | |
159 // the specified VT becomes active, at which point it will | |
160 // return." | |
161 | |
162 | |
163 const int activate_tty_error = ioctl( vt->tty, VT_ACTIVATE, vt->tty_ndx ); | |
164 const char* activate_tty_error_str = "Could not activate tty"; | |
165 | |
166 error_str = select_error_str( error, error_str, activate_tty_error, activate_tty_error_str ); | |
167 error = error | activate_tty_error; | |
168 | |
169 const int waitactive_tty_error = ioctl( vt->tty, VT_WAITACTIVE, vt->tty_ndx ); | |
170 const char* waitactive_tty_error_str = "Could not switch to tty"; | |
171 | |
172 error_str = select_error_str( error, error_str, waitactive_tty_error, waitactive_tty_error_str ); | |
173 error = error | waitactive_tty_error; | |
174 | |
175 // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt | |
176 // (Close enough to Linux and a pretty good source of documentation.) | |
177 // | |
178 // "KDSETMODE | |
179 // This call is used to set the text/graphics mode to the VT. | |
180 // | |
181 // KD_TEXT indicates that console text will be displayed on the screen | |
182 // with this VT. Normally KD_TEXT is combined with VT_AUTO mode for | |
183 // text console terminals, so that the console text display will | |
184 // automatically be saved and restored on the hot key screen switches. | |
185 // | |
186 // KD_GRAPHICS indicates that the user/application, usually Xserver, | |
187 // will have direct control of the display for this VT in graphics | |
188 // mode. Normally KD_GRAPHICS is combined with VT_PROCESS mode for | |
189 // this VT indicating direct control of the display in graphics mode. | |
190 // In this mode, all writes to this VT using the write system call are | |
191 // ignored, and the user is responsible for saving and restoring the | |
192 // display on the hot key screen switches." | |
193 | |
194 // Save the current VT mode. This is most likely KD_TEXT. | |
195 | |
196 const int kdgetmode_error = ioctl( vt->tty, KDGETMODE, &vt->prev_kdmode ); | |
197 const char* kdgetmode_error_str = "Could not get mode for tty"; | |
198 | |
199 error_str = select_error_str( error, error_str, kdgetmode_error, kdgetmode_error_str ); | |
200 error = error | kdgetmode_error; | |
201 | |
202 // Set VT to GRAPHICS (user draw) mode | |
203 | |
204 const int kdsetmode_graphics_error = ioctl( vt->tty, KDSETMODE, KD_GRAPHICS ); | |
205 const char* kdsetmode_graphics_error_str = "Could not set graphics mode for tty"; | |
206 | |
207 error_str = select_error_str( error, error_str, kdsetmode_graphics_error, kdsetmode_graphics_error_str ); | |
208 error = error | kdsetmode_graphics_error; | |
209 | |
210 // | |
211 // Not bothering with VT_PROCESS, VT_AUTO is fine for our purposes. | |
212 // | |
213 | |
214 // If vt blanking is active, for example when running this program from a remote terminal, | |
215 // setting KD_GRAPHICS will not disable the blanking. Reset to KD_TEXT from KD_GRAPHICS will | |
216 // force disable blanking. Then return to KD_GRAPHICS for drawing. | |
217 // | |
218 // Note: KD_TEXT (default) to KD_TEXT will do nothing, so blanking will not be disable unless | |
219 // the mode is changing. i.e. the initial set to KD_GRAPHICS above is useful. | |
220 | |
221 const int kdsetmode_text_error = ioctl( vt->tty, KDSETMODE, KD_TEXT ); | |
222 const char* kdsetmode_text_error_str = "Could not set text mode for tty"; | |
223 | |
224 error_str = select_error_str( error, error_str, kdsetmode_text_error, kdsetmode_text_error_str ); | |
225 error = error | kdsetmode_text_error; | |
226 | |
227 const int kdsetmode_graphics_reset_error = ioctl( vt->tty, KDSETMODE, KD_GRAPHICS ); | |
228 const char* kdsetmode_graphics_reset_error_str = "Could not reset graphics mode for tty"; | |
229 | |
230 error_str = select_error_str( error, error_str, kdsetmode_graphics_reset_error, kdsetmode_graphics_reset_error_str ); | |
231 error = error | kdsetmode_graphics_reset_error; | |
232 | |
233 if ( error == -1 ) | |
234 { | |
235 printf("ERROR: vt_graphics_open: %s\n",error_str); | |
236 return (-1); | |
237 } | |
238 | |
239 return (0); | |
240 } | |
241 | |
242 int | |
243 cp_vt_close(cp_vt* restrict vt) | |
244 { | |
245 const char* error_str = NULL; | |
246 int error = 0; | |
247 | |
248 // Reset previous mode on tty (likely KD_TEXT) | |
249 | |
250 const int kdsetmode_error = ioctl( vt->tty, KDSETMODE, vt->prev_kdmode ); | |
251 const char* kdsetmode_error_str = "Could not reset previous mode for tty"; | |
252 | |
253 error_str = select_error_str( error, error_str, kdsetmode_error, kdsetmode_error_str ); | |
254 error = error | kdsetmode_error; | |
255 | |
256 // Restore previous tty | |
257 | |
258 const int activate_tty_error = ioctl( vt->tty, VT_ACTIVATE, vt->prev_tty_ndx ); | |
259 const char* activate_tty_error_str = "Could not activate previous tty"; | |
260 | |
261 error_str = select_error_str( error, error_str, activate_tty_error, activate_tty_error_str ); | |
262 error = error | activate_tty_error; | |
263 | |
264 const int waitactive_tty_error = ioctl( vt->tty, VT_WAITACTIVE, vt->prev_tty_ndx ); | |
265 const char* waitactive_tty_error_str = "Could not switch to previous tty"; | |
266 | |
267 error_str = select_error_str( error, error_str, waitactive_tty_error, waitactive_tty_error_str ); | |
268 error = error | waitactive_tty_error; | |
269 | |
270 // Close tty | |
271 | |
272 const int close_tty_error = close( vt->tty ); | |
273 const char* close_tty_error_str = "Could not close tty"; | |
274 | |
275 error_str = select_error_str( error, error_str, close_tty_error, close_tty_error_str ); | |
276 error = error | close_tty_error; | |
277 | |
278 if ( error == -1 ) | |
279 { | |
280 printf("ERROR: vt_close: %s\n",error_str); | |
281 return (-1); | |
282 } | |
283 | |
284 return (0); | |
285 } |