fb.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:25k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * fb.c : framebuffer plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000, 2001 VideoLAN
  5.  * $Id: fb.c 8551 2004-08-28 17:36:02Z gbazin $
  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.  * Preamble
  25.  *****************************************************************************/
  26. #include <errno.h>                                                 /* ENOMEM */
  27. #include <signal.h>                                      /* SIGUSR1, SIGUSR2 */
  28. #include <stdlib.h>                                                /* free() */
  29. #include <string.h>                                            /* strerror() */
  30. #include <fcntl.h>                                                 /* open() */
  31. #include <unistd.h>                                               /* close() */
  32. #include <termios.h>                                       /* struct termios */
  33. #include <sys/ioctl.h>
  34. #include <sys/mman.h>                                              /* mmap() */
  35. #include <linux/fb.h>
  36. #include <linux/vt.h>                                                /* VT_* */
  37. #include <linux/kd.h>                                                 /* KD* */
  38. #include <vlc/vlc.h>
  39. #include <vlc/vout.h>
  40. /*****************************************************************************
  41.  * Local prototypes
  42.  *****************************************************************************/
  43. static int  Create    ( vlc_object_t * );
  44. static void Destroy   ( vlc_object_t * );
  45. static int  Init      ( vout_thread_t * );
  46. static void End       ( vout_thread_t * );
  47. static int  Manage    ( vout_thread_t * );
  48. static void Display   ( vout_thread_t *, picture_t * );
  49. static int  OpenDisplay    ( vout_thread_t * );
  50. static void CloseDisplay   ( vout_thread_t * );
  51. static void SwitchDisplay  ( int i_signal );
  52. static void TextMode       ( int i_tty );
  53. static void GfxMode        ( int i_tty );
  54. /*****************************************************************************
  55.  * Module descriptor
  56.  *****************************************************************************/
  57. #define FB_DEV_VAR "fbdev"
  58. #define DEVICE_TEXT N_("Framebuffer device")
  59. #define DEVICE_LONGTEXT N_( 
  60.     "You can select here the framebuffer device that will be used " 
  61.     "for rendering (usually /dev/fb0).")
  62. vlc_module_begin();
  63.     add_file( FB_DEV_VAR, "/dev/fb0", NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
  64.               VLC_FALSE );
  65.     set_description( _("GNU/Linux console framebuffer video output") );
  66.     set_capability( "video output", 30 );
  67.     set_callbacks( Create, Destroy );
  68. vlc_module_end();
  69. /*****************************************************************************
  70.  * vout_sys_t: video output framebuffer method descriptor
  71.  *****************************************************************************
  72.  * This structure is part of the video output thread descriptor.
  73.  * It describes the FB specific properties of an output thread.
  74.  *****************************************************************************/
  75. struct vout_sys_t
  76. {
  77.     /* System information */
  78.     int                 i_tty;                          /* tty device handle */
  79.     struct termios      old_termios;
  80.     /* Original configuration information */
  81.     struct sigaction            sig_usr1;           /* USR1 previous handler */
  82.     struct sigaction            sig_usr2;           /* USR2 previous handler */
  83.     struct vt_mode              vt_mode;                 /* previous VT mode */
  84.     /* Framebuffer information */
  85.     int                         i_fd;                       /* device handle */
  86.     struct fb_var_screeninfo    old_info;       /* original mode information */
  87.     struct fb_var_screeninfo    var_info;        /* current mode information */
  88.     vlc_bool_t                  b_pan;     /* does device supports panning ? */
  89.     struct fb_cmap              fb_cmap;                /* original colormap */
  90.     uint16_t                    *p_palette;              /* original palette */
  91.     /* Video information */
  92.     int i_width;
  93.     int i_height;
  94.     int i_bytes_per_pixel;
  95.     /* Video memory */
  96.     byte_t *    p_video;                                      /* base adress */
  97.     size_t      i_page_size;                                    /* page size */
  98. };
  99. /*****************************************************************************
  100.  * Create: allocates FB video thread output method
  101.  *****************************************************************************
  102.  * This function allocates and initializes a FB vout method.
  103.  *****************************************************************************/
  104. static int Create( vlc_object_t *p_this )
  105. {
  106.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  107.     struct sigaction    sig_tty;                 /* sigaction for tty change */
  108.     struct vt_mode      vt_mode;                          /* vt current mode */
  109.     struct termios      new_termios;
  110.     /* Allocate instance and initialize some members */
  111.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  112.     if( p_vout->p_sys == NULL )
  113.     {
  114.         return VLC_ENOMEM;
  115.     };
  116.     p_vout->pf_init = Init;
  117.     p_vout->pf_end = End;
  118.     p_vout->pf_manage = Manage;
  119.     p_vout->pf_render = NULL;
  120.     p_vout->pf_display = Display;
  121.     /* Set tty and fb devices */
  122.     p_vout->p_sys->i_tty = 0;           /* 0 == /dev/tty0 == current console */
  123.     GfxMode( p_vout->p_sys->i_tty );
  124.     /* Set keyboard settings */
  125.     if (tcgetattr(0, &p_vout->p_sys->old_termios) == -1)
  126.     {
  127.         msg_Err( p_vout, "tcgetattr failed" );
  128.     }
  129.     if (tcgetattr(0, &new_termios) == -1)
  130.     {
  131.         msg_Err( p_vout, "tcgetattr failed" );
  132.     }
  133.  /* new_termios.c_lflag &= ~ (ICANON | ISIG);
  134.     new_termios.c_lflag |= (ECHO | ECHOCTL); */
  135.     new_termios.c_lflag &= ~ (ICANON);
  136.     new_termios.c_lflag &= ~(ECHO | ECHOCTL);
  137.     new_termios.c_iflag = 0;
  138.     new_termios.c_cc[VMIN] = 1;
  139.     new_termios.c_cc[VTIME] = 0;
  140.     if (tcsetattr(0, TCSAFLUSH, &new_termios) == -1)
  141.     {
  142.         msg_Err( p_vout, "tcsetattr failed" );
  143.     }
  144.     ioctl( p_vout->p_sys->i_tty, VT_RELDISP, VT_ACKACQ );
  145.     /* Set-up tty signal handler to be aware of tty changes */
  146.     memset( &sig_tty, 0, sizeof( sig_tty ) );
  147.     sig_tty.sa_handler = SwitchDisplay;
  148.     sigemptyset( &sig_tty.sa_mask );
  149.     if( sigaction( SIGUSR1, &sig_tty, &p_vout->p_sys->sig_usr1 ) ||
  150.         sigaction( SIGUSR2, &sig_tty, &p_vout->p_sys->sig_usr2 ) )
  151.     {
  152.         msg_Err( p_vout, "cannot set signal handler (%s)", strerror(errno) );
  153.         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
  154.         TextMode( p_vout->p_sys->i_tty );
  155.         free( p_vout->p_sys );
  156.         return VLC_EGENERIC;
  157.     }
  158.     /* Set-up tty according to new signal handler */
  159.     if( -1 == ioctl( p_vout->p_sys->i_tty,
  160.                      VT_GETMODE, &p_vout->p_sys->vt_mode ) )
  161.     {
  162.         msg_Err( p_vout, "cannot get terminal mode (%s)", strerror(errno) );
  163.         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
  164.         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
  165.         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
  166.         TextMode( p_vout->p_sys->i_tty );
  167.         free( p_vout->p_sys );
  168.         return VLC_EGENERIC;
  169.     }
  170.     memcpy( &vt_mode, &p_vout->p_sys->vt_mode, sizeof( vt_mode ) );
  171.     vt_mode.mode   = VT_PROCESS;
  172.     vt_mode.waitv  = 0;
  173.     vt_mode.relsig = SIGUSR1;
  174.     vt_mode.acqsig = SIGUSR2;
  175.     if( -1 == ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &vt_mode ) )
  176.     {
  177.         msg_Err( p_vout, "cannot set terminal mode (%s)", strerror(errno) );
  178.         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
  179.         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
  180.         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
  181.         TextMode( p_vout->p_sys->i_tty );
  182.         free( p_vout->p_sys );
  183.         return VLC_EGENERIC;
  184.     }
  185.     if( OpenDisplay( p_vout ) )
  186.     {
  187.         ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode );
  188.         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
  189.         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
  190.         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
  191.         TextMode( p_vout->p_sys->i_tty );
  192.         free( p_vout->p_sys );
  193.         return VLC_EGENERIC;
  194.     }
  195.     return VLC_SUCCESS;
  196. }
  197. /*****************************************************************************
  198.  * Init: initialize framebuffer video thread output method
  199.  *****************************************************************************/
  200. static int Init( vout_thread_t *p_vout )
  201. {
  202.     int i_index;
  203.     picture_t *p_pic;
  204.     I_OUTPUTPICTURES = 0;
  205.     /* Initialize the output structure: RGB with square pixels, whatever
  206.      * the input format is, since it's the only format we know */
  207.     switch( p_vout->p_sys->var_info.bits_per_pixel )
  208.     {
  209.         case 8: /* FIXME: set the palette */
  210.             p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break;
  211.         case 15:
  212.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break;
  213.         case 16:
  214.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break;
  215.         case 24:
  216.             p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break;
  217.         case 32:
  218.             p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break;
  219.         default:
  220.             msg_Err( p_vout, "unknown screen depth %i",
  221.                      p_vout->p_sys->var_info.bits_per_pixel );
  222.             return VLC_EGENERIC;
  223.     }
  224.     /* Only useful for p_vout->p_sys->var_info.bits_per_pixel != 8 */
  225.     p_vout->output.i_rmask = ( (1 << p_vout->p_sys->var_info.red.length) - 1 )
  226.                      << p_vout->p_sys->var_info.red.offset;
  227.     p_vout->output.i_gmask = ( (1 << p_vout->p_sys->var_info.green.length) - 1 )
  228.                      << p_vout->p_sys->var_info.green.offset;
  229.     p_vout->output.i_bmask = ( (1 << p_vout->p_sys->var_info.blue.length) - 1 )
  230.                      << p_vout->p_sys->var_info.blue.offset;
  231.     p_vout->output.i_width = p_vout->p_sys->i_width;
  232.     p_vout->output.i_height = p_vout->p_sys->i_height;
  233.     /* Assume we have square pixels */
  234.     p_vout->output.i_aspect = p_vout->p_sys->i_width
  235.                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
  236.     /* Clear the screen */
  237.     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
  238.     /* Try to initialize 1 direct buffer */
  239.     p_pic = NULL;
  240.     /* Find an empty picture slot */
  241.     for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
  242.     {
  243.         if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
  244.         {
  245.             p_pic = p_vout->p_picture + i_index;
  246.             break;
  247.         }
  248.     }
  249.     /* Allocate the picture */
  250.     if( p_pic == NULL )
  251.     {
  252.         return VLC_EGENERIC;
  253.     }
  254.     /* We know the chroma, allocate a buffer which will be used
  255.      * directly by the decoder */
  256.     p_pic->p->p_pixels = p_vout->p_sys->p_video;
  257.     p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
  258.     p_pic->p->i_lines = p_vout->p_sys->var_info.yres;
  259.     p_pic->p->i_visible_lines = p_vout->p_sys->var_info.yres;
  260.     if( p_vout->p_sys->var_info.xres_virtual )
  261.     {
  262.         p_pic->p->i_pitch = p_vout->p_sys->var_info.xres_virtual
  263.                              * p_vout->p_sys->i_bytes_per_pixel;
  264.     }
  265.     else
  266.     {
  267.         p_pic->p->i_pitch = p_vout->p_sys->var_info.xres
  268.                              * p_vout->p_sys->i_bytes_per_pixel;
  269.     }
  270.     p_pic->p->i_visible_pitch = p_vout->p_sys->var_info.xres
  271.                                  * p_vout->p_sys->i_bytes_per_pixel;
  272.     p_pic->i_planes = 1;
  273.     p_pic->i_status = DESTROYED_PICTURE;
  274.     p_pic->i_type   = DIRECT_PICTURE;
  275.     PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
  276.     I_OUTPUTPICTURES++;
  277.     return VLC_SUCCESS;
  278. }
  279. /*****************************************************************************
  280.  * End: terminate framebuffer video thread output method
  281.  *****************************************************************************/
  282. static void End( vout_thread_t *p_vout )
  283. {
  284.     /* Clear the screen */
  285.     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
  286. }
  287. /*****************************************************************************
  288.  * Destroy: destroy FB video thread output method
  289.  *****************************************************************************
  290.  * Terminate an output method created by Create
  291.  *****************************************************************************/
  292. static void Destroy( vlc_object_t *p_this )
  293. {
  294.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  295.     CloseDisplay( p_vout );
  296.     /* Reset the terminal */
  297.     ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode );
  298.     /* Remove signal handlers */
  299.     sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
  300.     sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
  301.     /* Reset the keyboard state */
  302.     tcsetattr( 0, 0, &p_vout->p_sys->old_termios );
  303.     /* Return to text mode */
  304.     TextMode( p_vout->p_sys->i_tty );
  305.     /* Destroy structure */
  306.     free( p_vout->p_sys );
  307. }
  308. /*****************************************************************************
  309.  * Manage: handle FB events
  310.  *****************************************************************************
  311.  * This function should be called regularly by video output thread. It manages
  312.  * console events. It returns a non null value on error.
  313.  *****************************************************************************/
  314. static int Manage( vout_thread_t *p_vout )
  315. {
  316. #if 0
  317.     uint8_t buf;
  318.     if ( read(0, &buf, 1) == 1)
  319.     {
  320.         switch( buf )
  321.         {
  322.         case 'q':
  323.             p_vout->p_vlc->b_die = 1;
  324.             break;
  325.         default:
  326.             break;
  327.         }
  328.     }
  329. #endif
  330.     /*
  331.      * Size change
  332.      */
  333.     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
  334.     {
  335.         msg_Dbg( p_vout, "reinitializing framebuffer screen" );
  336.         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
  337.         /* Destroy XImages to change their size */
  338.         End( p_vout );
  339.         /* Recreate XImages. If SysInit failed, the thread can't go on. */
  340.         if( Init( p_vout ) )
  341.         {
  342.             msg_Err( p_vout, "cannot reinit framebuffer screen" );
  343.             return VLC_EGENERIC;
  344.         }
  345.         /* Clear screen */
  346.         memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
  347. #if 0
  348.         /* Tell the video output thread that it will need to rebuild YUV
  349.          * tables. This is needed since conversion buffer size may have changed */
  350.         p_vout->i_changes |= VOUT_YUV_CHANGE;
  351. #endif
  352.     }
  353.     return VLC_SUCCESS;
  354. }
  355. /*****************************************************************************
  356.  * Display: displays previously rendered output
  357.  *****************************************************************************
  358.  * This function send the currently rendered image to FB image, waits until
  359.  * it is displayed and switch the two rendering buffers, preparing next frame.
  360.  *****************************************************************************/
  361. static void Display( vout_thread_t *p_vout, picture_t *p_pic )
  362. {
  363. static int panned=0;
  364.     /* swap the two Y offsets if the drivers supports panning */
  365.     if( p_vout->p_sys->b_pan )
  366.     {
  367.         p_vout->p_sys->var_info.yoffset = 0;
  368.         /*p_vout->p_sys->var_info.yoffset = p_vout->p_sys->var_info.yres; */
  369.         /* the X offset should be 0, but who knows ...
  370.          * some other app might have played with the framebuffer */
  371.         p_vout->p_sys->var_info.xoffset = 0;
  372. if(panned < 0) {
  373.         ioctl( p_vout->p_sys->i_fd,
  374.                FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );
  375. panned++;
  376. }
  377.     }
  378. }
  379. #if 0
  380. static void SetPalette( vout_thread_t *p_vout, uint16_t *red, uint16_t *green,
  381.                                                uint16_t *blue, uint16_t *transp )
  382. {
  383.     struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
  384.     ioctl( p_vout->p_sys->i_fd, FBIOPUTCMAP, &cmap );
  385. }
  386. #endif
  387. /* following functions are local */
  388. /*****************************************************************************
  389.  * OpenDisplay: initialize framebuffer
  390.  *****************************************************************************/
  391. static int OpenDisplay( vout_thread_t *p_vout )
  392. {
  393.     char *psz_device;                             /* framebuffer device path */
  394.     struct fb_fix_screeninfo    fix_info;     /* framebuffer fix information */
  395.     /* Open framebuffer device */
  396.     if( !(psz_device = config_GetPsz( p_vout, FB_DEV_VAR )) )
  397.     {
  398.         msg_Err( p_vout, "don't know which fb device to open" );
  399.         return VLC_EGENERIC;
  400.     }
  401.     p_vout->p_sys->i_fd = open( psz_device, O_RDWR);
  402.     if( p_vout->p_sys->i_fd == -1 )
  403.     {
  404.         msg_Err( p_vout, "cannot open %s (%s)", psz_device, strerror(errno) );
  405.         free( psz_device );
  406.         return VLC_EGENERIC;
  407.     }
  408.     free( psz_device );
  409.     /* Get framebuffer device information */
  410.     if( ioctl( p_vout->p_sys->i_fd,
  411.                FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
  412.     {
  413.         msg_Err( p_vout, "cannot get fb info (%s)", strerror(errno) );
  414.         close( p_vout->p_sys->i_fd );
  415.         return VLC_EGENERIC;
  416.     }
  417.     memcpy( &p_vout->p_sys->old_info, &p_vout->p_sys->var_info,
  418.             sizeof( struct fb_var_screeninfo ) );
  419.     /* Set some attributes */
  420.     p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN;
  421.     p_vout->p_sys->var_info.xoffset =  0;
  422.     p_vout->p_sys->var_info.yoffset =  0;
  423.     if( ioctl( p_vout->p_sys->i_fd,
  424.                FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
  425.     {
  426.         msg_Err( p_vout, "cannot set fb info (%s)", strerror(errno) );
  427.         close( p_vout->p_sys->i_fd );
  428.         return VLC_EGENERIC;
  429.     }
  430.     /* Get some information again, in the definitive configuration */
  431.     if( ioctl( p_vout->p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info )
  432.          || ioctl( p_vout->p_sys->i_fd,
  433.                    FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
  434.     {
  435.         msg_Err( p_vout, "cannot get additional fb info (%s)",
  436.                           strerror(errno) );
  437.         /* Restore fb config */
  438.         ioctl( p_vout->p_sys->i_fd,
  439.                FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
  440.         close( p_vout->p_sys->i_fd );
  441.         return VLC_EGENERIC;
  442.     }
  443.     /* FIXME: if the image is full-size, it gets cropped on the left
  444.      * because of the xres / xres_virtual slight difference */
  445.     msg_Dbg( p_vout, "%ix%i (virtual %ix%i)",
  446.              p_vout->p_sys->var_info.xres, p_vout->p_sys->var_info.yres,
  447.              p_vout->p_sys->var_info.xres_virtual,
  448.              p_vout->p_sys->var_info.yres_virtual );
  449.     p_vout->p_sys->i_height = p_vout->p_sys->var_info.yres;
  450.     p_vout->p_sys->i_width  = p_vout->p_sys->var_info.xres_virtual
  451.                                ? p_vout->p_sys->var_info.xres_virtual
  452.                                : p_vout->p_sys->var_info.xres;
  453.     p_vout->p_sys->p_palette = NULL;
  454.     p_vout->p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
  455.     switch( p_vout->p_sys->var_info.bits_per_pixel )
  456.     {
  457.     case 8:
  458.         p_vout->p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) );
  459.         p_vout->p_sys->fb_cmap.start = 0;
  460.         p_vout->p_sys->fb_cmap.len = 256;
  461.         p_vout->p_sys->fb_cmap.red = p_vout->p_sys->p_palette;
  462.         p_vout->p_sys->fb_cmap.green = p_vout->p_sys->p_palette + 256 * sizeof( uint16_t );
  463.         p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->p_palette + 2 * 256 * sizeof( uint16_t );
  464.         p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->p_palette + 3 * 256 * sizeof( uint16_t );
  465.         /* Save the colormap */
  466.         ioctl( p_vout->p_sys->i_fd, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
  467.         p_vout->p_sys->i_bytes_per_pixel = 1;
  468.         break;
  469.     case 15:
  470.     case 16:
  471.         p_vout->p_sys->i_bytes_per_pixel = 2;
  472.         break;
  473.     case 24:
  474.         p_vout->p_sys->i_bytes_per_pixel = 3;
  475.         break;
  476.     case 32:
  477.         p_vout->p_sys->i_bytes_per_pixel = 4;
  478.         break;
  479.     default:
  480.         msg_Err( p_vout, "screen depth %d is not supported",
  481.                          p_vout->p_sys->var_info.bits_per_pixel );
  482.         /* Restore fb config */
  483.         ioctl( p_vout->p_sys->i_fd,
  484.                FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
  485.         close( p_vout->p_sys->i_fd );
  486.         return VLC_EGENERIC;
  487.     }
  488.     p_vout->p_sys->i_page_size = p_vout->p_sys->i_width *
  489.                 p_vout->p_sys->i_height * p_vout->p_sys->i_bytes_per_pixel;
  490.     /* Map a framebuffer at the beginning */
  491.     p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->i_page_size,
  492.                                    PROT_READ | PROT_WRITE, MAP_SHARED,
  493.                                    p_vout->p_sys->i_fd, 0 );
  494.     if( p_vout->p_sys->p_video == ((void*)-1) )
  495.     {
  496.         msg_Err( p_vout, "cannot map video memory (%s)", strerror(errno) );
  497.         if( p_vout->p_sys->var_info.bits_per_pixel == 8 )
  498.         {
  499.             free( p_vout->p_sys->p_palette );
  500.         }
  501.         /* Restore fb config */
  502.         ioctl( p_vout->p_sys->i_fd,
  503.                FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
  504.         close( p_vout->p_sys->i_fd );
  505.         return VLC_EGENERIC;
  506.     }
  507.     msg_Dbg( p_vout, "framebuffer type=%d, visual=%d, ypanstep=%d, "
  508.              "ywrap=%d, accel=%d", fix_info.type, fix_info.visual,
  509.              fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
  510.     return VLC_SUCCESS;
  511. }
  512. /*****************************************************************************
  513.  * CloseDisplay: terminate FB video thread output method
  514.  *****************************************************************************/
  515. static void CloseDisplay( vout_thread_t *p_vout )
  516. {
  517.     /* Clear display */
  518.     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );
  519.     /* Restore palette */
  520.     if( p_vout->p_sys->var_info.bits_per_pixel == 8 )
  521.     {
  522.         ioctl( p_vout->p_sys->i_fd,
  523.                FBIOPUTCMAP, &p_vout->p_sys->fb_cmap );
  524.         free( p_vout->p_sys->p_palette );
  525.     }
  526.     /* Restore fb config */
  527.     ioctl( p_vout->p_sys->i_fd,
  528.            FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info );
  529.     /* Close fb */
  530.     close( p_vout->p_sys->i_fd );
  531. }
  532. /*****************************************************************************
  533.  * SwitchDisplay: VT change signal handler
  534.  *****************************************************************************
  535.  * This function activates or deactivates the output of the thread. It is
  536.  * called by the VT driver, on terminal change.
  537.  *****************************************************************************/
  538. static void SwitchDisplay(int i_signal)
  539. {
  540. #if 0
  541.     vout_thread_t *p_vout;
  542.     vlc_mutex_lock( &p_vout_bank->lock );
  543.     /* XXX: only test the first video output */
  544.     if( p_vout_bank->i_count )
  545.     {
  546.         p_vout = p_vout_bank->pp_vout[0];
  547.         switch( i_signal )
  548.         {
  549.         case SIGUSR1:                                /* vt has been released */
  550.             p_vout->b_active = 0;
  551.             ioctl( p_vout->p_sys->i_tty, VT_RELDISP, 1 );
  552.             break;
  553.         case SIGUSR2:                                /* vt has been acquired */
  554.             p_vout->b_active = 1;
  555.             ioctl( p_vout->p_sys->i_tty, VT_RELDISP, VT_ACTIVATE );
  556.             /* handle blanking */
  557.             vlc_mutex_lock( &p_vout->change_lock );
  558.             p_vout->i_changes |= VOUT_SIZE_CHANGE;
  559.             vlc_mutex_unlock( &p_vout->change_lock );
  560.             break;
  561.         }
  562.     }
  563.     vlc_mutex_unlock( &p_vout_bank->lock );
  564. #endif
  565. }
  566. /*****************************************************************************
  567.  * TextMode and GfxMode : switch tty to text/graphic mode
  568.  *****************************************************************************
  569.  * These functions toggle the tty mode.
  570.  *****************************************************************************/
  571. static void TextMode( int i_tty )
  572. {
  573.     /* return to text mode */
  574.     if( -1 == ioctl(i_tty, KDSETMODE, KD_TEXT) )
  575.     {
  576.         /*msg_Err( p_vout, "failed ioctl KDSETMODE KD_TEXT" );*/
  577.     }
  578. }
  579. static void GfxMode( int i_tty )
  580. {
  581.     /* switch to graphic mode */
  582.     if( -1 == ioctl(i_tty, KDSETMODE, KD_GRAPHICS) )
  583.     {
  584.         /*msg_Err( p_vout, "failed ioctl KDSETMODE KD_GRAPHICS" );*/
  585.     }
  586. }