]> git.sesse.net Git - vlc/blob - modules/video_output/fb.c
vout_fb: cosmetics, else on the same line than closing }
[vlc] / modules / video_output / fb.c
1 /*****************************************************************************
2  * fb.c : framebuffer plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Jean-Paul Saman
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <errno.h>                                                 /* ENOMEM */
34 #include <signal.h>                                      /* SIGUSR1, SIGUSR2 */
35 #include <fcntl.h>                                                 /* open() */
36 #include <unistd.h>                                               /* close() */
37
38 #include <termios.h>                                       /* struct termios */
39 #include <sys/ioctl.h>
40 #include <sys/mman.h>                                              /* mmap() */
41
42 #include <linux/fb.h>
43 #include <linux/vt.h>                                                /* VT_* */
44 #include <linux/kd.h>                                                 /* KD* */
45
46 #include <vlc_common.h>
47 #include <vlc_plugin.h>
48 #include <vlc_vout_display.h>
49 #include <vlc_picture_pool.h>
50 #include <vlc_charset.h>
51
52 /*****************************************************************************
53  * Module descriptor
54  *****************************************************************************/
55 #define FB_DEV_VAR "fbdev"
56
57 #define DEVICE_TEXT N_("Framebuffer device")
58 #define DEVICE_LONGTEXT N_(\
59     "Framebuffer device to use for rendering (usually /dev/fb0).")
60
61 #define TTY_TEXT N_("Run fb on current tty.")
62 #define TTY_LONGTEXT N_(\
63     "Run framebuffer on current TTY device (default enabled). " \
64     "(disable tty handling with caution)")
65
66 #define FB_MODE_TEXT N_("Framebuffer resolution to use.")
67 #define FB_MODE_LONGTEXT N_(\
68     "Select the resolution for the framebuffer. Currently it supports " \
69     "the values 0=QCIF 1=CIF 2=NTSC 3=PAL, 4=auto (default 4=auto)")
70
71 #define HW_ACCEL_TEXT N_("Framebuffer uses hw acceleration.")
72 #define HW_ACCEL_LONGTEXT N_(\
73     "If your framebuffer supports hardware acceleration or does double buffering " \
74     "in hardware then you must disable this option. It then does double buffering " \
75     "in software.")
76
77 #define CHROMA_TEXT N_("Image format (default RGB).")
78 #define CHROMA_LONGTEXT N_("Chroma fourcc used by the framebuffer. Default is RGB since the fb device has no way to report its chroma.")
79
80 static int  Open (vlc_object_t *);
81 static void Close(vlc_object_t *);
82
83 vlc_module_begin ()
84     set_shortname("Framebuffer")
85     set_category(CAT_VIDEO)
86     set_subcategory(SUBCAT_VIDEO_VOUT)
87     add_file(FB_DEV_VAR, "/dev/fb0", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
88               false)
89     add_bool("fb-tty", true, NULL, TTY_TEXT, TTY_LONGTEXT, true)
90     add_string( "fb-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true )
91     add_obsolete_string("fb-aspect-ratio")
92     add_integer("fb-mode", 4, NULL, FB_MODE_TEXT, FB_MODE_LONGTEXT,
93                  true)
94     add_bool("fb-hw-accel", true, NULL, HW_ACCEL_TEXT, HW_ACCEL_LONGTEXT,
95               true)
96     set_description(N_("GNU/Linux framebuffer video output"))
97     set_capability("vout display", 30)
98     set_callbacks(Open, Close)
99 vlc_module_end ()
100
101 /*****************************************************************************
102  * Local prototypes
103  *****************************************************************************/
104 static picture_pool_t *Pool  (vout_display_t *, unsigned);
105 static void           Display(vout_display_t *, picture_t *);
106 static int            Control(vout_display_t *, int, va_list);
107 static void           Manage (vout_display_t *);
108
109 /* */
110 static int  OpenDisplay  (vout_display_t *, bool force_resolution);
111 static void CloseDisplay (vout_display_t *);
112 static void SwitchDisplay(int i_signal);
113 static void TextMode     (int tty);
114 static void GfxMode      (int tty);
115
116 static int  TtyInit(vout_display_t *);
117 static void TtyExit(vout_display_t *);
118
119 /* */
120 struct vout_display_sys_t {
121     /* System information */
122     int                 tty;                          /* tty device handle */
123     bool                is_tty;
124     struct termios      old_termios;
125
126     /* Original configuration information */
127     struct sigaction            sig_usr1;           /* USR1 previous handler */
128     struct sigaction            sig_usr2;           /* USR2 previous handler */
129     struct vt_mode              vt_mode;                 /* previous VT mode */
130
131     /* Framebuffer information */
132     int                         fd;                       /* device handle */
133     struct fb_var_screeninfo    old_info;       /* original mode information */
134     struct fb_var_screeninfo    var_info;        /* current mode information */
135     bool                        has_pan;   /* does device supports panning ? */
136     struct fb_cmap              fb_cmap;                /* original colormap */
137     uint16_t                    *palette;                /* original palette */
138     bool                        is_hw_accel;         /* has hardware support */
139
140     /* Video information */
141     uint32_t width;
142     uint32_t height;
143     uint32_t line_length;
144     vlc_fourcc_t chroma;
145     int      bytes_per_pixel;
146
147     /* Video memory */
148     uint8_t     *video_ptr;                                  /* base adress */
149     size_t      video_size;                                    /* page size */
150
151     picture_t       *picture;
152     picture_pool_t  *pool;
153 };
154
155
156 static void ClearScreen(vout_display_sys_t *sys)
157 {
158     switch (sys->chroma) {
159     /* XXX: add other chromas */
160     case VLC_CODEC_UYVY: {
161         unsigned int j, size = sys->video_size / 4;
162         uint32_t *ptr = (uint32_t*)((uintptr_t)(sys->video_ptr + 3) & ~3);
163         for(j=0; j < size; j++)
164             ptr[j] = 0x10801080;    /* U = V = 16, Y = 128 */
165         break;
166     }
167     default:    /* RGB */
168         memset(sys->video_ptr, 0, sys->video_size);
169     }
170 }
171
172 /**
173  * This function allocates and initializes a FB vout method.
174  */
175 static int Open(vlc_object_t *object)
176 {
177     vout_display_t     *vd = (vout_display_t *)object;
178     vout_display_sys_t *sys;
179
180     /* Allocate instance and initialize some members */
181     vd->sys = sys = calloc(1, sizeof(*sys));
182     if (!sys)
183         return VLC_ENOMEM;
184
185     /* Does the framebuffer uses hw acceleration? */
186     sys->is_hw_accel = var_CreateGetBool(vd, "fb-hw-accel");
187
188     /* Set tty and fb devices */
189     sys->tty = 0; /* 0 == /dev/tty0 == current console */
190     sys->is_tty = var_CreateGetBool(vd, "fb-tty");
191 #if !defined(WIN32) &&  defined(HAVE_ISATTY)
192     /* Check that stdin is a TTY */
193     if (sys->is_tty && !isatty(0)) {
194         msg_Warn(vd, "fd 0 is not a TTY");
195         free(sys);
196         return VLC_EGENERIC;
197     }
198     msg_Warn(vd, "disabling tty handling, use with caution because "
199                  "there is no way to return to the tty.");
200 #endif
201
202     const int mode = var_CreateGetInteger(vd, "fb-mode");
203     bool force_resolution = true;
204     switch (mode) {
205     case 0: /* QCIF */
206         sys->width  = 176;
207         sys->height = 144;
208         break;
209     case 1: /* CIF */
210         sys->width  = 352;
211         sys->height = 288;
212         break;
213     case 2: /* NTSC */
214         sys->width  = 640;
215         sys->height = 480;
216         break;
217     case 3: /* PAL */
218         sys->width  = 704;
219         sys->height = 576;
220         break;
221     case 4:
222     default:
223         force_resolution = false;
224         break;
225     }
226
227     char *chroma = var_CreateGetNonEmptyString(vd, "fb-chroma");
228     if (chroma) {
229         sys->chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma);
230
231         if (sys->chroma)
232             msg_Dbg(vd, "forcing chroma '%s'", chroma);
233         else
234             msg_Warn(vd, "chroma %s invalid, using default", chroma);
235
236         free(chroma);
237     } else
238         sys->chroma = 0;
239
240     /* tty handling */
241     if (sys->is_tty && TtyInit(vd)) {
242         free(sys);
243         return VLC_EGENERIC;
244     }
245
246     /* */
247     sys->video_ptr = MAP_FAILED;
248     sys->picture = NULL;
249     sys->pool = NULL;
250
251     if (OpenDisplay(vd, force_resolution)) {
252         Close(VLC_OBJECT(vd));
253         return VLC_EGENERIC;
254     }
255
256     /* */
257     video_format_t fmt = vd->fmt;
258
259     if (sys->chroma) {
260         fmt.i_chroma = sys->chroma;
261     } else {
262         /* Assume RGB */
263
264         msg_Dbg(vd, "%d bppd", sys->var_info.bits_per_pixel);
265         switch (sys->var_info.bits_per_pixel) {
266         case 8: /* FIXME: set the palette */
267             fmt.i_chroma = VLC_CODEC_RGB8;
268             break;
269         case 15:
270             fmt.i_chroma = VLC_CODEC_RGB15;
271             break;
272         case 16:
273             fmt.i_chroma = VLC_CODEC_RGB16;
274             break;
275         case 24:
276             fmt.i_chroma = VLC_CODEC_RGB24;
277             break;
278         case 32:
279             fmt.i_chroma = VLC_CODEC_RGB32;
280             break;
281         default:
282             msg_Err(vd, "unknown screendepth %i", sys->var_info.bits_per_pixel);
283             Close(VLC_OBJECT(vd));
284             return VLC_EGENERIC;
285         }
286         if (sys->var_info.bits_per_pixel != 8) {
287             fmt.i_rmask = ((1 << sys->var_info.red.length) - 1)
288                                  << sys->var_info.red.offset;
289             fmt.i_gmask = ((1 << sys->var_info.green.length) - 1)
290                                  << sys->var_info.green.offset;
291             fmt.i_bmask = ((1 << sys->var_info.blue.length) - 1)
292                                  << sys->var_info.blue.offset;
293         }
294     }
295
296     fmt.i_width  = sys->width;
297     fmt.i_height = sys->height;
298
299     /* */
300     vout_display_info_t info = vd->info;
301     info.has_hide_mouse = true;
302
303     /* */
304     vd->fmt     = fmt;
305     vd->info    = info;
306     vd->pool    = Pool;
307     vd->prepare = NULL;
308     vd->display = Display;
309     vd->control = Control;
310     vd->manage  = Manage;
311
312     /* */
313     vout_display_SendEventFullscreen(vd, true);
314     vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, true);
315     return VLC_SUCCESS;
316 }
317
318 /**
319  * Terminate an output method created by Open
320  */
321 static void Close(vlc_object_t *object)
322 {
323     vout_display_t *vd = (vout_display_t *)object;
324     vout_display_sys_t *sys = vd->sys;
325
326     if (sys->pool)
327         picture_pool_Delete(sys->pool);
328     if (!sys->is_hw_accel && sys->picture)
329         picture_Release(sys->picture);
330
331     CloseDisplay(vd);
332
333     if (sys->is_tty)
334         TtyExit(vd);
335
336     free(sys);
337 }
338
339 /* */
340 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
341 {
342     vout_display_sys_t *sys = vd->sys;
343
344     if (!sys->pool) {
345         if (!sys->picture) {
346             picture_resource_t rsc;
347
348             memset(&rsc, 0, sizeof(rsc));
349             rsc.p[0].p_pixels = sys->video_ptr;
350             rsc.p[0].i_lines  = sys->var_info.yres;
351             rsc.p[0].i_pitch = sys->line_length;
352
353             sys->picture = picture_NewFromResource(&vd->fmt, &rsc);
354             if (!sys->picture)
355                 return NULL;
356         }
357
358         if (sys->is_hw_accel)
359             sys->pool = picture_pool_New(1, &sys->picture);
360         else
361             sys->pool = picture_pool_NewFromFormat(&vd->fmt, count);
362     }
363     return sys->pool;
364 }
365 static void Display(vout_display_t *vd, picture_t *picture)
366 {
367     vout_display_sys_t *sys = vd->sys;
368
369     /* swap the two Y offsets if the drivers supports panning */
370     if (sys->has_pan) {
371         sys->var_info.yoffset = 0;
372         /*vd->sys->var_info.yoffset = vd->sys->var_info.yres; */
373
374         /* the X offset should be 0, but who knows ...
375          * some other app might have played with the framebuffer */
376         sys->var_info.xoffset = 0;
377
378         /* FIXME 'static' is damn wrong and it's dead code ... */
379         static int panned = 0;
380         if (panned < 0) {
381             ioctl(sys->fd, FBIOPAN_DISPLAY, &sys->var_info);
382             panned++;
383         }
384     }
385
386     if (!sys->is_hw_accel)
387         picture_Copy(sys->picture, picture);
388
389     picture_Release(picture);
390 }
391 static int Control(vout_display_t *vd, int query, va_list args)
392 {
393     vout_display_sys_t *sys = vd->sys;
394
395     switch (query) {
396     case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
397         const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
398         if (cfg->display.width  != sys->width ||
399             cfg->display.height != sys->height)
400             return VLC_EGENERIC;
401         return VLC_SUCCESS;
402     }
403     default:
404         msg_Err(vd, "Unsupported query in vout display fb");
405         return VLC_EGENERIC;
406     }
407 }
408 static void Manage (vout_display_t *vd)
409 {
410     VLC_UNUSED(vd);
411 #if 0
412     /*
413      * Size change
414      */
415     if (vd->i_changes & VOUT_SIZE_CHANGE)
416     {
417         msg_Dbg(vd, "reinitializing framebuffer screen");
418         vd->i_changes &= ~VOUT_SIZE_CHANGE;
419
420         vout_display_SendEventDisplaySize();
421
422         ClearScreen(vd->sys);
423     }
424 #endif
425 }
426
427 /* following functions are local */
428 static int TtyInit(vout_display_t *vd)
429 {
430     vout_display_sys_t *sys = vd->sys;
431
432     struct termios new_termios;
433
434     GfxMode(sys->tty);
435
436     /* Set keyboard settings */
437     if (tcgetattr(0, &sys->old_termios) == -1) {
438         msg_Err(vd, "tcgetattr failed");
439     }
440
441     if (tcgetattr(0, &new_termios) == -1) {
442         msg_Err(vd, "tcgetattr failed");
443     }
444
445     /* new_termios.c_lflag &= ~ (ICANON | ISIG);
446     new_termios.c_lflag |= (ECHO | ECHOCTL); */
447     new_termios.c_lflag &= ~ (ICANON);
448     new_termios.c_lflag &= ~(ECHO | ECHOCTL);
449     new_termios.c_iflag = 0;
450     new_termios.c_cc[VMIN] = 1;
451     new_termios.c_cc[VTIME] = 0;
452
453     if (tcsetattr(0, TCSAFLUSH, &new_termios) == -1) {
454         msg_Err(vd, "tcsetattr failed");
455     }
456
457     ioctl(sys->tty, VT_RELDISP, VT_ACKACQ);
458
459     /* Set-up tty signal handler to be aware of tty changes */
460     struct sigaction sig_tty;
461     memset(&sig_tty, 0, sizeof(sig_tty));
462     sig_tty.sa_handler = SwitchDisplay;
463     sigemptyset(&sig_tty.sa_mask);
464     if (sigaction(SIGUSR1, &sig_tty, &sys->sig_usr1) ||
465         sigaction(SIGUSR2, &sig_tty, &sys->sig_usr2)) {
466         msg_Err(vd, "cannot set signal handler (%m)");
467         /* FIXME SIGUSR1 could have succeed */
468         goto error_signal;
469     }
470
471     /* Set-up tty according to new signal handler */
472     if (-1 == ioctl(sys->tty, VT_GETMODE, &sys->vt_mode)) {
473         msg_Err(vd, "cannot get terminal mode (%m)");
474         goto error;
475     }
476     struct vt_mode vt_mode = sys->vt_mode;
477     vt_mode.mode   = VT_PROCESS;
478     vt_mode.waitv  = 0;
479     vt_mode.relsig = SIGUSR1;
480     vt_mode.acqsig = SIGUSR2;
481
482     if (-1 == ioctl(sys->tty, VT_SETMODE, &vt_mode)) {
483         msg_Err(vd, "cannot set terminal mode (%m)");
484         goto error;
485     }
486     return VLC_SUCCESS;
487
488 error:
489     sigaction(SIGUSR1, &sys->sig_usr1, NULL);
490     sigaction(SIGUSR2, &sys->sig_usr2, NULL);
491 error_signal:
492     tcsetattr(0, 0, &sys->old_termios);
493     TextMode(sys->tty);
494     return VLC_EGENERIC;
495 }
496 static void TtyExit(vout_display_t *vd)
497 {
498     vout_display_sys_t *sys = vd->sys;
499
500     /* Reset the terminal */
501     ioctl(sys->tty, VT_SETMODE, &sys->vt_mode);
502
503     /* Remove signal handlers */
504     sigaction(SIGUSR1, &sys->sig_usr1, NULL);
505     sigaction(SIGUSR2, &sys->sig_usr2, NULL);
506
507     /* Reset the keyboard state */
508     tcsetattr(0, 0, &sys->old_termios);
509
510     /* Return to text mode */
511     TextMode(sys->tty);
512 }
513
514 /*****************************************************************************
515  * OpenDisplay: initialize framebuffer
516  *****************************************************************************/
517 static int OpenDisplay(vout_display_t *vd, bool force_resolution)
518 {
519     vout_display_sys_t *sys = vd->sys;
520     char *psz_device;                             /* framebuffer device path */
521
522     /* Open framebuffer device */
523     if (!(psz_device = config_GetPsz(vd, FB_DEV_VAR))) {
524         msg_Err(vd, "don't know which fb device to open");
525         return VLC_EGENERIC;
526     }
527
528     sys->fd = utf8_open(psz_device, O_RDWR);
529     if (sys->fd == -1) {
530         msg_Err(vd, "cannot open %s (%m)", psz_device);
531         free(psz_device);
532         return VLC_EGENERIC;
533     }
534     free(psz_device);
535
536     /* Get framebuffer device information */
537     if (ioctl(sys->fd, FBIOGET_VSCREENINFO, &sys->var_info)) {
538         msg_Err(vd, "cannot get fb info (%m)");
539         close(sys->fd);
540         return VLC_EGENERIC;
541     }
542     sys->old_info = sys->var_info;
543
544     /* Get some info on the framebuffer itself */
545     if (force_resolution) {
546         sys->var_info.xres = sys->var_info.xres_virtual = sys->width;
547         sys->var_info.yres = sys->var_info.yres_virtual = sys->height;
548     }
549
550     /* Set some attributes */
551     sys->var_info.activate = sys->is_tty ? FB_ACTIVATE_NXTOPEN :
552                                            FB_ACTIVATE_NOW;
553     sys->var_info.xoffset  =  0;
554     sys->var_info.yoffset  =  0;
555
556     if (ioctl(sys->fd, FBIOPUT_VSCREENINFO, &sys->var_info)) {
557         msg_Err(vd, "cannot set fb info (%m)");
558         close(sys->fd);
559         return VLC_EGENERIC;
560     }
561
562     struct fb_fix_screeninfo fix_info;
563     /* Get some information again, in the definitive configuration */
564     if (ioctl(sys->fd, FBIOGET_FSCREENINFO, &fix_info) ||
565         ioctl(sys->fd, FBIOGET_VSCREENINFO, &sys->var_info)) {
566         msg_Err(vd, "cannot get additional fb info (%m)");
567
568         /* Restore fb config */
569         ioctl(sys->fd, FBIOPUT_VSCREENINFO, &sys->old_info);
570
571         close(sys->fd);
572         return VLC_EGENERIC;
573     }
574
575     /* If the fb has limitations on mode change,
576      * then keep the resolution of the fb */
577     if ((sys->height != sys->var_info.yres) ||
578         (sys->width != sys->var_info.xres)) {
579         msg_Warn(vd,
580                  "using framebuffer native resolution instead of requested (%ix%i)",
581                  sys->width, sys->height);
582     }
583     sys->height = sys->var_info.yres;
584     sys->width  = sys->var_info.xres_virtual ? sys->var_info.xres_virtual :
585                                                sys->var_info.xres;
586     sys->line_length = fix_info.line_length;
587
588     /* FIXME: if the image is full-size, it gets cropped on the left
589      * because of the xres / xres_virtual slight difference */
590     msg_Dbg(vd, "%ix%i (virtual %ix%i) (request %ix%i)",
591             sys->var_info.xres, sys->var_info.yres,
592             sys->var_info.xres_virtual,
593             sys->var_info.yres_virtual,
594             sys->width, sys->height);
595
596     sys->palette = NULL;
597     sys->has_pan = (fix_info.ypanstep || fix_info.ywrapstep);
598
599     switch (sys->var_info.bits_per_pixel) {
600     case 8:
601         sys->palette = malloc(8 * 256 * sizeof(uint16_t));
602         if (!sys->palette) {
603             /* Restore fb config */
604             ioctl(sys->fd, FBIOPUT_VSCREENINFO, &sys->old_info);
605
606             close(sys->fd);
607             return VLC_ENOMEM;
608         }
609         sys->fb_cmap.start = 0;
610         sys->fb_cmap.len = 256;
611         sys->fb_cmap.red = sys->palette;
612         sys->fb_cmap.green = sys->palette + 256 * sizeof(uint16_t);
613         sys->fb_cmap.blue = sys->palette + 2 * 256 * sizeof(uint16_t);
614         sys->fb_cmap.transp = sys->palette + 3 * 256 * sizeof(uint16_t);
615
616         /* Save the colormap */
617         ioctl(sys->fd, FBIOGETCMAP, &sys->fb_cmap);
618
619         sys->bytes_per_pixel = 1;
620         break;
621
622     case 15:
623     case 16:
624         sys->bytes_per_pixel = 2;
625         break;
626
627     case 24:
628         sys->bytes_per_pixel = 3;
629         break;
630
631     case 32:
632         sys->bytes_per_pixel = 4;
633         break;
634
635     default:
636         msg_Err(vd, "screen depth %d is not supported",
637                 sys->var_info.bits_per_pixel);
638
639         /* Restore fb config */
640         ioctl(sys->fd, FBIOPUT_VSCREENINFO, &sys->old_info);
641
642         close(sys->fd);
643         return VLC_EGENERIC;
644     }
645
646     sys->video_size = sys->line_length * sys->var_info.yres_virtual;
647
648     /* Map a framebuffer at the beginning */
649     sys->video_ptr = mmap(NULL, sys->video_size,
650                           PROT_READ | PROT_WRITE, MAP_SHARED, sys->fd, 0);
651
652     if (sys->video_ptr == MAP_FAILED) {
653         msg_Err(vd, "cannot map video memory (%m)");
654
655         if (sys->var_info.bits_per_pixel == 8) {
656             free(sys->palette);
657             sys->palette = NULL;
658         }
659
660         /* Restore fb config */
661         ioctl(sys->fd, FBIOPUT_VSCREENINFO, &sys->old_info);
662
663         close(sys->fd);
664         return VLC_EGENERIC;
665     }
666
667     ClearScreen(sys);
668
669     msg_Dbg(vd,
670             "framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d",
671             fix_info.type, fix_info.visual,
672             fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel);
673     return VLC_SUCCESS;
674 }
675
676 /*****************************************************************************
677  * CloseDisplay: terminate FB video thread output method
678  *****************************************************************************/
679 static void CloseDisplay(vout_display_t *vd)
680 {
681     vout_display_sys_t *sys = vd->sys;
682
683     if (sys->video_ptr != MAP_FAILED) {
684         ClearScreen(sys);
685         munmap(sys->video_ptr, sys->video_size);
686     }
687
688     if (sys->fd >= 0) {
689         /* Restore palette */
690         if (sys->var_info.bits_per_pixel == 8) {
691             ioctl(sys->fd, FBIOPUTCMAP, &sys->fb_cmap);
692             free(sys->palette);
693             sys->palette = NULL;
694         }
695
696         /* Restore fb config */
697         ioctl(sys->fd, FBIOPUT_VSCREENINFO, &sys->old_info);
698
699         /* Close fb */
700         close(sys->fd);
701     }
702 }
703
704 /*****************************************************************************
705  * SwitchDisplay: VT change signal handler
706  *****************************************************************************
707  * This function activates or deactivates the output of the thread. It is
708  * called by the VT driver, on terminal change.
709  *****************************************************************************/
710 static void SwitchDisplay(int i_signal)
711 {
712     VLC_UNUSED(i_signal);
713 #if 0
714     vout_display_t *vd;
715
716     vlc_mutex_lock(&p_vout_bank->lock);
717
718     /* XXX: only test the first video output */
719     if (p_vout_bank->i_count)
720     {
721         vd = p_vout_bank->pp_vout[0];
722
723         switch (i_signal)
724         {
725         case SIGUSR1:                                /* vt has been released */
726             vd->b_active = 0;
727             ioctl(sys->tty, VT_RELDISP, 1);
728             break;
729         case SIGUSR2:                                /* vt has been acquired */
730             vd->b_active = 1;
731             ioctl(sys->tty, VT_RELDISP, VT_ACTIVATE);
732             /* handle blanking */
733             vlc_mutex_lock(&vd->change_lock);
734             vd->i_changes |= VOUT_SIZE_CHANGE;
735             vlc_mutex_unlock(&vd->change_lock);
736             break;
737         }
738     }
739
740     vlc_mutex_unlock(&p_vout_bank->lock);
741 #endif
742 }
743
744 /*****************************************************************************
745  * TextMode and GfxMode : switch tty to text/graphic mode
746  *****************************************************************************
747  * These functions toggle the tty mode.
748  *****************************************************************************/
749 static void TextMode(int tty)
750 {
751     /* return to text mode */
752     if (-1 == ioctl(tty, KDSETMODE, KD_TEXT)) {
753         /*msg_Err(vd, "failed ioctl KDSETMODE KD_TEXT");*/
754     }
755 }
756
757 static void GfxMode(int tty)
758 {
759     /* switch to graphic mode */
760     if (-1 == ioctl(tty, KDSETMODE, KD_GRAPHICS)) {
761         /*msg_Err(vd, "failed ioctl KDSETMODE KD_GRAPHICS");*/
762     }
763 }