]> git.sesse.net Git - vlc/blob - plugins/fb/vout_fb.c
* Fixed the BeOS compile typo.
[vlc] / plugins / fb / vout_fb.c
1 /*****************************************************************************
2  * vout_fb.c: framebuffer video output display method
3  *****************************************************************************
4  * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
5  * $Id: vout_fb.c,v 1.13 2001/05/30 17:03:12 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #define MODULE_NAME fb
25 #include "modules_inner.h"
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include "defs.h"
31
32 #include <errno.h>                                                 /* ENOMEM */
33 #include <signal.h>                                      /* SIGUSR1, SIGUSR2 */
34 #include <stdlib.h>                                                /* free() */
35 #include <string.h>                                            /* strerror() */
36 #include <fcntl.h>                                                 /* open() */
37 #include <unistd.h>                                               /* close() */
38
39 #include <termios.h>                                       /* struct termios */
40 #include <sys/ioctl.h>
41 #include <sys/mman.h>                                              /* mmap() */
42
43 #include <linux/fb.h>
44 #include <linux/vt.h>                                                /* VT_* */
45 #include <linux/kd.h>                                                 /* KD* */
46
47 #include "config.h"
48 #include "common.h"
49 #include "threads.h"
50 #include "mtime.h"
51 #include "tests.h"
52 #include "modules.h"
53
54 #include "video.h"
55 #include "video_output.h"
56
57 #include "intf_msg.h"
58 #include "main.h"
59
60 #include "modules_export.h"
61
62 /*****************************************************************************
63  * vout_sys_t: video output framebuffer method descriptor
64  *****************************************************************************
65  * This structure is part of the video output thread descriptor.
66  * It describes the FB specific properties of an output thread.
67  *****************************************************************************/
68 typedef struct vout_sys_s
69 {
70     /* System informations */
71     int                 i_tty_dev;                      /* tty device handle */
72     struct termios      old_termios;
73
74     /* Original configuration informations */
75     struct sigaction            sig_usr1;           /* USR1 previous handler */
76     struct sigaction            sig_usr2;           /* USR2 previous handler */
77     struct vt_mode              vt_mode;                 /* previous VT mode */
78
79     /* Framebuffer information */
80     int                         i_fb_dev;                   /* device handle */
81     struct fb_var_screeninfo    old_info;      /* original mode informations */
82     struct fb_var_screeninfo    var_info;       /* current mode informations */
83     boolean_t                   b_pan;     /* does device supports panning ? */
84     struct fb_cmap              fb_cmap;                /* original colormap */
85     u16                         *fb_palette;             /* original palette */
86
87     /* Video memory */
88     byte_t *                    p_video;                      /* base adress */
89     size_t                      i_page_size;                    /* page size */
90
91 } vout_sys_t;
92
93 /*****************************************************************************
94  * Local prototypes.
95  *****************************************************************************/
96 static int  vout_Probe     ( probedata_t *p_data );
97 static int  vout_Create    ( struct vout_thread_s * );
98 static int  vout_Init      ( struct vout_thread_s * );
99 static void vout_End       ( struct vout_thread_s * );
100 static void vout_Destroy   ( struct vout_thread_s * );
101 static int  vout_Manage    ( struct vout_thread_s * );
102 static void vout_Display   ( struct vout_thread_s * );
103 static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
104                              u16 *blue, u16 *transp );
105
106 static int  FBOpenDisplay  ( struct vout_thread_s * );
107 static void FBCloseDisplay ( struct vout_thread_s * );
108 static void FBSwitchDisplay( int i_signal );
109 static void FBTextMode     ( int i_tty_dev );
110 static void FBGfxMode      ( int i_tty_dev );
111
112 /*****************************************************************************
113  * Functions exported as capabilities. They are declared as static so that
114  * we don't pollute the namespace too much.
115  *****************************************************************************/
116 void _M( vout_getfunctions )( function_list_t * p_function_list )
117 {
118     p_function_list->pf_probe = vout_Probe;
119     p_function_list->functions.vout.pf_create     = vout_Create;
120     p_function_list->functions.vout.pf_init       = vout_Init;
121     p_function_list->functions.vout.pf_end        = vout_End;
122     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
123     p_function_list->functions.vout.pf_manage     = vout_Manage;
124     p_function_list->functions.vout.pf_display    = vout_Display;
125     p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
126 }
127
128 /*****************************************************************************
129  * vout_Probe: probe the video driver and return a score
130  *****************************************************************************
131  * This function tries to open the framebuffer and returns a score to the
132  * plugin manager so that it can select the best plugin.
133  *****************************************************************************/
134 static int vout_Probe( probedata_t *p_data )
135 {
136     int i_fd;
137
138     if( TestMethod( VOUT_METHOD_VAR, "fb" ) )
139     {
140         return( 999 );
141     }
142
143     i_fd = open( main_GetPszVariable( VOUT_FB_DEV_VAR,
144                                       VOUT_FB_DEV_DEFAULT ), O_RDWR );
145     if( i_fd == -1 )
146     {
147         return( 0 );
148     }
149     close( i_fd );
150
151     return( 30 );
152 }
153
154 /*****************************************************************************
155  * vout_Create: allocates FB video thread output method
156  *****************************************************************************
157  * This function allocates and initializes a FB vout method.
158  *****************************************************************************/
159 static int vout_Create( vout_thread_t *p_vout )
160 {
161     struct sigaction    sig_tty;                 /* sigaction for tty change */
162     struct vt_mode      vt_mode;                          /* vt current mode */
163     struct termios      new_termios;
164
165     /* Allocate instance and initialize some members */
166     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
167     if( p_vout->p_sys == NULL )
168     {
169         return( 1 );
170     };
171
172     /* Set tty and fb devices */
173     p_vout->p_sys->i_tty_dev = 0;       /* 0 == /dev/tty0 == current console */
174
175     FBGfxMode( p_vout->p_sys->i_tty_dev );
176
177     /* Set keyboard settings */
178     if (tcgetattr(0, &p_vout->p_sys->old_termios) == -1)
179     {
180         intf_ErrMsg( "intf error: tcgetattr" );
181     }
182
183     if (tcgetattr(0, &new_termios) == -1)
184     {
185         intf_ErrMsg( "intf error: tcgetattr" );
186     }
187
188  /* new_termios.c_lflag &= ~ (ICANON | ISIG);
189     new_termios.c_lflag |= (ECHO | ECHOCTL); */
190     new_termios.c_lflag &= ~ (ICANON);
191     new_termios.c_lflag &= ~(ECHO | ECHOCTL);
192     new_termios.c_iflag = 0;
193     new_termios.c_cc[VMIN] = 1;
194     new_termios.c_cc[VTIME] = 0;
195
196     if (tcsetattr(0, TCSAFLUSH, &new_termios) == -1)
197     {
198         intf_ErrMsg( "intf error: tcsetattr" );
199     }
200
201     ioctl(p_vout->p_sys->i_tty_dev, VT_RELDISP, VT_ACKACQ);
202
203     /* Set-up tty signal handler to be aware of tty changes */
204     memset( &sig_tty, 0, sizeof( sig_tty ) );
205     sig_tty.sa_handler = FBSwitchDisplay;
206     sigemptyset( &sig_tty.sa_mask );
207     if( sigaction( SIGUSR1, &sig_tty, &p_vout->p_sys->sig_usr1 ) ||
208         sigaction( SIGUSR2, &sig_tty, &p_vout->p_sys->sig_usr2 ) )
209     {
210         intf_ErrMsg( "intf error: can't set up signal handler (%s)",
211                      strerror(errno) );
212         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
213         FBTextMode( p_vout->p_sys->i_tty_dev );
214         free( p_vout->p_sys );
215         return( 1 );
216     }
217
218     /* Set-up tty according to new signal handler */
219     if( ioctl(p_vout->p_sys->i_tty_dev, VT_GETMODE, &p_vout->p_sys->vt_mode)
220         == -1 )
221     {
222         intf_ErrMsg( "intf error: cant get terminal mode (%s)",
223                      strerror(errno) );
224         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
225         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
226         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
227         FBTextMode( p_vout->p_sys->i_tty_dev );
228         free( p_vout->p_sys );
229         return( 1 );
230     }
231     memcpy( &vt_mode, &p_vout->p_sys->vt_mode, sizeof( vt_mode ) );
232     vt_mode.mode   = VT_PROCESS;
233     vt_mode.waitv  = 0;
234     vt_mode.relsig = SIGUSR1;
235     vt_mode.acqsig = SIGUSR2;
236
237     if( ioctl(p_vout->p_sys->i_tty_dev, VT_SETMODE, &vt_mode) == -1 )
238     {
239         intf_ErrMsg( "intf error: can't set terminal mode (%s)",
240                      strerror(errno) );
241         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
242         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
243         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
244         FBTextMode( p_vout->p_sys->i_tty_dev );
245         free( p_vout->p_sys );
246         return( 1 );
247     }
248
249     if( FBOpenDisplay( p_vout ) )
250     {
251         ioctl(p_vout->p_sys->i_tty_dev, VT_SETMODE, &p_vout->p_sys->vt_mode);
252         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
253         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
254         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
255         FBTextMode( p_vout->p_sys->i_tty_dev );
256         free( p_vout->p_sys );
257         return( 1 );
258     }
259
260     return( 0 );
261 }
262
263 /*****************************************************************************
264  * vout_Init: initialize framebuffer video thread output method
265  *****************************************************************************/
266 static int vout_Init( vout_thread_t *p_vout )
267 {
268     /* Clear the screen */
269     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
270
271     return( 0 );
272 }
273
274 /*****************************************************************************
275  * vout_End: terminate framebuffer video thread output method
276  *****************************************************************************/
277 static void vout_End( vout_thread_t *p_vout )
278 {
279     /* Clear the screen */
280     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
281 }
282
283 /*****************************************************************************
284  * vout_Destroy: destroy FB video thread output method
285  *****************************************************************************
286  * Terminate an output method created by vout_CreateOutputMethod
287  *****************************************************************************/
288 static void vout_Destroy( vout_thread_t *p_vout )
289 {
290     FBCloseDisplay( p_vout );
291
292     /* Reset the terminal */
293     ioctl(p_vout->p_sys->i_tty_dev, VT_SETMODE, &p_vout->p_sys->vt_mode);
294
295     /* Remove signal handlers */
296     sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
297     sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
298
299     /* Reset the keyboard state */
300     tcsetattr( 0, 0, &p_vout->p_sys->old_termios );
301
302     /* Return to text mode */
303     FBTextMode( p_vout->p_sys->i_tty_dev );
304
305     /* Destroy structure */
306     free( p_vout->p_sys );
307 }
308
309 /*****************************************************************************
310  * vout_Manage: handle FB events
311  *****************************************************************************
312  * This function should be called regularly by video output thread. It manages
313  * console events. It returns a non null value on error.
314  *****************************************************************************/
315 static int vout_Manage( vout_thread_t *p_vout )
316 {
317 #if 0
318     u8 buf;
319
320     if ( read(0, &buf, 1) == 1)
321     {
322         switch( buf )
323         {
324         case 'q':
325             p_main->p_intf->b_die = 1;
326             break;
327
328         default:
329             break;
330         }
331     }
332 #endif
333
334     /*
335      * Size change
336      */
337     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
338     {
339         intf_WarnMsg( 3, "vout: reinitializing framebuffer screen" );
340         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
341
342         /* Destroy XImages to change their size */
343         vout_End( p_vout );
344
345         /* Recreate XImages. If SysInit failed, the thread can't go on. */
346         if( vout_Init( p_vout ) )
347         {
348             intf_ErrMsg("error: cannot reinit framebuffer screen" );
349             return( 1 );
350         }
351
352         /* Clear screen */
353         memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
354
355 #if 1
356         /* Tell the video output thread that it will need to rebuild YUV
357          * tables. This is needed since conversion buffer size may have changed */
358         p_vout->i_changes |= VOUT_YUV_CHANGE;
359 #endif
360     }
361
362     return 0;
363 }
364
365 /*****************************************************************************
366  * vout_Display: displays previously rendered output
367  *****************************************************************************
368  * This function send the currently rendered image to FB image, waits until
369  * it is displayed and switch the two rendering buffers, preparing next frame.
370  *****************************************************************************/
371 static void vout_Display( vout_thread_t *p_vout )
372 {
373     /* swap the two Y offsets if the drivers supports panning */
374     if( p_vout->p_sys->b_pan )
375     {
376         p_vout->p_sys->var_info.yoffset =
377             p_vout->i_buffer_index ? p_vout->p_sys->var_info.yres : 0;
378    
379         /* the X offset should be 0, but who knows ...
380          * some other app might have played with the framebuffer */
381         p_vout->p_sys->var_info.xoffset = 0;
382
383         ioctl( p_vout->p_sys->i_fb_dev,
384                FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );
385     }
386 }
387
388 /*****************************************************************************
389  * vout_SetPalette: sets an 8 bpp palette
390  *****************************************************************************
391  * This function sets the palette given as an argument. It does not return
392  * anything, but could later send information on which colors it was unable
393  * to set.
394  *****************************************************************************/
395 static void vout_SetPalette( p_vout_thread_t p_vout,
396                              u16 *red, u16 *green, u16 *blue, u16 *transp )
397 {
398     struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
399
400     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );
401 }
402
403 /* following functions are local */
404
405 /*****************************************************************************
406  * FBOpenDisplay: initialize framebuffer
407  *****************************************************************************/
408 static int FBOpenDisplay( vout_thread_t *p_vout )
409 {
410     char *psz_device;                             /* framebuffer device path */
411     struct fb_fix_screeninfo    fix_info;     /* framebuffer fix information */
412
413     /* Open framebuffer device */
414     psz_device = main_GetPszVariable( VOUT_FB_DEV_VAR, VOUT_FB_DEV_DEFAULT );
415     p_vout->p_sys->i_fb_dev = open( psz_device, O_RDWR);
416     if( p_vout->p_sys->i_fb_dev == -1 )
417     {
418         intf_ErrMsg("vout error: can't open %s (%s)", psz_device, strerror(errno) );
419         return( 1 );
420     }
421
422     /* Get framebuffer device informations */
423     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
424     {
425         intf_ErrMsg("vout error: can't get fb info (%s)", strerror(errno) );
426         close( p_vout->p_sys->i_fb_dev );
427         return( 1 );
428     }
429
430     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->old_info ) )
431     {
432         intf_ErrMsg("vout error: can't get 2nd fb info (%s)", strerror(errno) );
433         close( p_vout->p_sys->i_fb_dev );
434         return( 1 );
435     }
436
437     /* Set some attributes */
438     p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN;
439     p_vout->p_sys->var_info.xoffset =  0;
440     p_vout->p_sys->var_info.yoffset =  0;
441
442     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
443     {
444         intf_ErrMsg(" vout error: can't set fb info (%s)", strerror(errno) );
445         close( p_vout->p_sys->i_fb_dev );
446         return( 1 );
447     }
448
449     /* Get some informations again, in the definitive configuration */
450     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_FSCREENINFO, &fix_info ) ||
451         ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
452     {
453         intf_ErrMsg(" vout error: can't get additional fb info (%s)", strerror(errno) );
454
455         /* Restore fb config */
456         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
457
458         close( p_vout->p_sys->i_fb_dev );
459         return( 1 );
460     }
461
462     /* FIXME: if the image is full-size, it gets cropped on the left
463      * because of the xres / xres_virtual slight difference */
464     intf_WarnMsg( 3, "vout: %ix%i (virtual %ix%i)",
465                   p_vout->p_sys->var_info.xres,
466                   p_vout->p_sys->var_info.yres,
467                   p_vout->p_sys->var_info.xres_virtual,
468                   p_vout->p_sys->var_info.yres_virtual );
469
470     p_vout->i_height = p_vout->p_sys->var_info.yres;
471     p_vout->i_width  = p_vout->p_sys->var_info.xres_virtual ?
472                            p_vout->p_sys->var_info.xres_virtual
473                            : p_vout->p_sys->var_info.xres;
474
475     p_vout->i_screen_depth = p_vout->p_sys->var_info.bits_per_pixel;
476
477     p_vout->p_sys->fb_palette = NULL;
478     p_vout->p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
479
480     switch( p_vout->i_screen_depth )
481     {
482     case 8:                                                         /* 8 bpp */
483         p_vout->p_sys->fb_palette = malloc( 8 * 256 * sizeof( u16 ) );
484         p_vout->p_sys->fb_cmap.start = 0;
485         p_vout->p_sys->fb_cmap.len = 256;
486         p_vout->p_sys->fb_cmap.red = p_vout->p_sys->fb_palette;
487         p_vout->p_sys->fb_cmap.green = p_vout->p_sys->fb_palette + 256 * sizeof( u16 );
488         p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->fb_palette + 2 * 256 * sizeof( u16 );
489         p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->fb_palette + 3 * 256 * sizeof( u16 );
490
491         /* Save the colormap */
492         ioctl( p_vout->p_sys->i_fb_dev, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
493
494         p_vout->i_bytes_per_pixel = 1;
495         p_vout->i_bytes_per_line = p_vout->i_width;
496         break;
497
498     case 15:                      /* 15 bpp (16bpp with a missing green bit) */
499     case 16:                                        /* 16 bpp (65536 colors) */
500         p_vout->i_bytes_per_pixel = 2;
501         p_vout->i_bytes_per_line = p_vout->i_width * 2;
502         break;
503
504     case 24:                                  /* 24 bpp (millions of colors) */
505         p_vout->i_bytes_per_pixel = 3;
506         p_vout->i_bytes_per_line = p_vout->i_width * 3;
507         break;
508
509     case 32:                                  /* 32 bpp (millions of colors) */
510         p_vout->i_bytes_per_pixel = 4;
511         p_vout->i_bytes_per_line = p_vout->i_width * 4;
512         break;
513
514     default:                                     /* unsupported screen depth */
515         intf_ErrMsg( "vout error: screen depth %d is not supported",
516                      p_vout->i_screen_depth);
517
518         /* Restore fb config */
519         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
520
521         close( p_vout->p_sys->i_fb_dev );
522         return( 1 );
523         break;
524     }
525
526     switch( p_vout->i_screen_depth )
527     {
528     case 15:
529     case 16:
530     case 24:
531     case 32:
532         p_vout->i_red_mask =    ( (1 << p_vout->p_sys->var_info.red.length) - 1 )
533                                     << p_vout->p_sys->var_info.red.offset;
534         p_vout->i_green_mask =    ( (1 << p_vout->p_sys->var_info.green.length) - 1 )
535                                     << p_vout->p_sys->var_info.green.offset;
536         p_vout->i_blue_mask =    ( (1 << p_vout->p_sys->var_info.blue.length) - 1 )
537                                     << p_vout->p_sys->var_info.blue.offset;
538     }
539
540     p_vout->p_sys->i_page_size = p_vout->i_width *
541                 p_vout->i_height * p_vout->i_bytes_per_pixel;
542
543     /* Map two framebuffers a the very beginning of the fb */
544     p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->i_page_size * 2,
545                                    PROT_READ | PROT_WRITE, MAP_SHARED,
546                                    p_vout->p_sys->i_fb_dev, 0 );
547
548     if( (int)p_vout->p_sys->p_video == -1 ) /* according to man, it is -1.
549                                                What about NULL ? */
550     {
551         intf_ErrMsg("vout error: can't map video memory (%s)", strerror(errno) );
552         /* FIXME: restore fb config ?? */
553         if( p_vout->i_screen_depth == 8 )
554         {
555             free( p_vout->p_sys->fb_palette );
556         }
557
558         /* Restore fb config */
559         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
560
561         close( p_vout->p_sys->i_fb_dev );
562         return( 1 );
563     }
564
565     /* Set and initialize buffers */
566     if( p_vout->p_sys->b_pan )
567     {
568         p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_video,
569                                  p_vout->p_sys->p_video
570                                   + p_vout->p_sys->i_page_size );
571     }
572     else
573     {
574         p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_video,
575                                  p_vout->p_sys->p_video );
576     }
577     
578     intf_WarnMsg( 3, "framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d",
579                   fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
580     return( 0 );
581 }
582
583 /*****************************************************************************
584  * FBCloseDisplay: terminate FB video thread output method
585  *****************************************************************************/
586 static void FBCloseDisplay( vout_thread_t *p_vout )
587 {
588     /* Clear display */
589     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
590
591     /* Restore palette */
592     if( p_vout->i_screen_depth == 8 );
593     {
594         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &p_vout->p_sys->fb_cmap );
595         free( p_vout->p_sys->fb_palette );
596     }
597
598     /* Restore fb config */
599     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
600
601     /* Close fb */
602     close( p_vout->p_sys->i_fb_dev );
603 }
604
605 /*****************************************************************************
606  * FBSwitchDisplay: VT change signal handler
607  *****************************************************************************
608  * This function activates or deactivates the output of the thread. It is
609  * called by the VT driver, on terminal change.
610  *****************************************************************************/
611 static void FBSwitchDisplay(int i_signal)
612 {
613 #if 0
614     vout_thread_t *p_vout;
615
616     vlc_mutex_lock( &p_vout_bank->lock );
617
618     /* XXX: only test the first video output */
619     if( p_vout_bank->i_count )
620     {
621         p_vout = p_vout_bank->pp_vout[0];
622
623         switch( i_signal )
624         {
625         case SIGUSR1:                                /* vt has been released */
626             p_vout->b_active = 0;
627             ioctl( p_vout->p_sys->i_tty_dev, VT_RELDISP, 1 );
628             break;
629         case SIGUSR2:                                /* vt has been acquired */
630             p_vout->b_active = 1;
631             ioctl( p_vout->p_sys->i_tty_dev, VT_RELDISP, VT_ACTIVATE );
632             /* handle blanking */
633             vlc_mutex_lock( &p_vout->change_lock );
634             p_vout->i_changes |= VOUT_SIZE_CHANGE;
635             vlc_mutex_unlock( &p_vout->change_lock );
636             break;
637         }
638     }
639
640     vlc_mutex_unlock( &p_vout_bank->lock );
641 #endif
642 }
643
644 /*****************************************************************************
645  * FBTextMode and FBGfxMode : switch tty to text/graphic mode
646  *****************************************************************************
647  * These functions toggle the tty mode.
648  *****************************************************************************/
649 static void FBTextMode( int i_tty_dev )
650 {
651     /* return to text mode */
652     if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_TEXT))
653     {
654         intf_ErrMsg( "intf error: failed ioctl KDSETMODE KD_TEXT" );
655     }
656 }
657
658 static void FBGfxMode( int i_tty_dev )
659 {
660     /* switch to graphic mode */
661     if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_GRAPHICS))
662     {
663         intf_ErrMsg( "intf error: failed ioctl KDSETMODE KD_GRAPHICS" );
664     }
665 }
666