📄 fb.c
字号:
ioctl( p_vout->p_sys->i_tty, VT_SETMODE, &p_vout->p_sys->vt_mode ); /* Remove signal handlers */ sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL ); sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL ); /* Reset the keyboard state */ tcsetattr( 0, 0, &p_vout->p_sys->old_termios ); /* Return to text mode */ TextMode( p_vout->p_sys->i_tty ); /* Destroy structure */ free( p_vout->p_sys );}/***************************************************************************** * Manage: handle FB events ***************************************************************************** * This function should be called regularly by video output thread. It manages * console events. It returns a non null value on error. *****************************************************************************/static int Manage( vout_thread_t *p_vout ){#if 0 uint8_t buf; if ( read(0, &buf, 1) == 1) { switch( buf ) { case 'q': p_vout->p_vlc->b_die = 1; break; default: break; } }#endif /* * Size change */ if( p_vout->i_changes & VOUT_SIZE_CHANGE ) { msg_Dbg( p_vout, "reinitializing framebuffer screen" ); p_vout->i_changes &= ~VOUT_SIZE_CHANGE; /* Destroy XImages to change their size */ End( p_vout ); /* Recreate XImages. If SysInit failed, the thread can't go on. */ if( Init( p_vout ) ) { msg_Err( p_vout, "cannot reinit framebuffer screen" ); return VLC_EGENERIC; } /* Clear screen */ memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size );#if 0 /* Tell the video output thread that it will need to rebuild YUV * tables. This is needed since conversion buffer size may have changed */ p_vout->i_changes |= VOUT_YUV_CHANGE;#endif } return VLC_SUCCESS;}/***************************************************************************** * Display: displays previously rendered output ***************************************************************************** * This function send the currently rendered image to FB image, waits until * it is displayed and switch the two rendering buffers, preparing next frame. *****************************************************************************/static void Display( vout_thread_t *p_vout, picture_t *p_pic ){static int panned=0; /* swap the two Y offsets if the drivers supports panning */ if( p_vout->p_sys->b_pan ) { p_vout->p_sys->var_info.yoffset = 0; /*p_vout->p_sys->var_info.yoffset = p_vout->p_sys->var_info.yres; */ /* the X offset should be 0, but who knows ... * some other app might have played with the framebuffer */ p_vout->p_sys->var_info.xoffset = 0;if(panned < 0) { ioctl( p_vout->p_sys->i_fd, FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );panned++;} }}#if 0static void SetPalette( vout_thread_t *p_vout, uint16_t *red, uint16_t *green, uint16_t *blue, uint16_t *transp ){ struct fb_cmap cmap = { 0, 256, red, green, blue, transp }; ioctl( p_vout->p_sys->i_fd, FBIOPUTCMAP, &cmap );}#endif/* following functions are local *//***************************************************************************** * OpenDisplay: initialize framebuffer *****************************************************************************/static int OpenDisplay( vout_thread_t *p_vout ){ char *psz_device; /* framebuffer device path */ struct fb_fix_screeninfo fix_info; /* framebuffer fix information */ /* Open framebuffer device */ if( !(psz_device = config_GetPsz( p_vout, FB_DEV_VAR )) ) { msg_Err( p_vout, "don't know which fb device to open" ); return VLC_EGENERIC; } p_vout->p_sys->i_fd = open( psz_device, O_RDWR); if( p_vout->p_sys->i_fd == -1 ) { msg_Err( p_vout, "cannot open %s (%s)", psz_device, strerror(errno) ); free( psz_device ); return VLC_EGENERIC; } free( psz_device ); /* Get framebuffer device information */ if( ioctl( p_vout->p_sys->i_fd, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) ) { msg_Err( p_vout, "cannot get fb info (%s)", strerror(errno) ); close( p_vout->p_sys->i_fd ); return VLC_EGENERIC; } memcpy( &p_vout->p_sys->old_info, &p_vout->p_sys->var_info, sizeof( struct fb_var_screeninfo ) ); /* Set some attributes */ p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN; p_vout->p_sys->var_info.xoffset = 0; p_vout->p_sys->var_info.yoffset = 0; if( ioctl( p_vout->p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) ) { msg_Err( p_vout, "cannot set fb info (%s)", strerror(errno) ); close( p_vout->p_sys->i_fd ); return VLC_EGENERIC; } /* Get some information again, in the definitive configuration */ if( ioctl( p_vout->p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) || ioctl( p_vout->p_sys->i_fd, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) ) { msg_Err( p_vout, "cannot get additional fb info (%s)", strerror(errno) ); /* Restore fb config */ ioctl( p_vout->p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info ); close( p_vout->p_sys->i_fd ); return VLC_EGENERIC; } /* FIXME: if the image is full-size, it gets cropped on the left * because of the xres / xres_virtual slight difference */ msg_Dbg( p_vout, "%ix%i (virtual %ix%i)", p_vout->p_sys->var_info.xres, p_vout->p_sys->var_info.yres, p_vout->p_sys->var_info.xres_virtual, p_vout->p_sys->var_info.yres_virtual ); p_vout->p_sys->i_height = p_vout->p_sys->var_info.yres; p_vout->p_sys->i_width = p_vout->p_sys->var_info.xres_virtual ? p_vout->p_sys->var_info.xres_virtual : p_vout->p_sys->var_info.xres; p_vout->p_sys->p_palette = NULL; p_vout->p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep ); switch( p_vout->p_sys->var_info.bits_per_pixel ) { case 8: p_vout->p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) ); p_vout->p_sys->fb_cmap.start = 0; p_vout->p_sys->fb_cmap.len = 256; p_vout->p_sys->fb_cmap.red = p_vout->p_sys->p_palette; p_vout->p_sys->fb_cmap.green = p_vout->p_sys->p_palette + 256 * sizeof( uint16_t ); p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->p_palette + 2 * 256 * sizeof( uint16_t ); p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->p_palette + 3 * 256 * sizeof( uint16_t ); /* Save the colormap */ ioctl( p_vout->p_sys->i_fd, FBIOGETCMAP, &p_vout->p_sys->fb_cmap ); p_vout->p_sys->i_bytes_per_pixel = 1; break; case 15: case 16: p_vout->p_sys->i_bytes_per_pixel = 2; break; case 24: p_vout->p_sys->i_bytes_per_pixel = 3; break; case 32: p_vout->p_sys->i_bytes_per_pixel = 4; break; default: msg_Err( p_vout, "screen depth %d is not supported", p_vout->p_sys->var_info.bits_per_pixel ); /* Restore fb config */ ioctl( p_vout->p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info ); close( p_vout->p_sys->i_fd ); return VLC_EGENERIC; } p_vout->p_sys->i_page_size = p_vout->p_sys->i_width * p_vout->p_sys->i_height * p_vout->p_sys->i_bytes_per_pixel; /* Map a framebuffer at the beginning */ p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->i_page_size, PROT_READ | PROT_WRITE, MAP_SHARED, p_vout->p_sys->i_fd, 0 ); if( p_vout->p_sys->p_video == ((void*)-1) ) { msg_Err( p_vout, "cannot map video memory (%s)", strerror(errno) ); if( p_vout->p_sys->var_info.bits_per_pixel == 8 ) { free( p_vout->p_sys->p_palette ); } /* Restore fb config */ ioctl( p_vout->p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info ); close( p_vout->p_sys->i_fd ); return VLC_EGENERIC; } msg_Dbg( p_vout, "framebuffer type=%d, visual=%d, ypanstep=%d, " "ywrap=%d, accel=%d", fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel ); return VLC_SUCCESS;}/***************************************************************************** * CloseDisplay: terminate FB video thread output method *****************************************************************************/static void CloseDisplay( vout_thread_t *p_vout ){ /* Clear display */ memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size ); /* Restore palette */ if( p_vout->p_sys->var_info.bits_per_pixel == 8 ) { ioctl( p_vout->p_sys->i_fd, FBIOPUTCMAP, &p_vout->p_sys->fb_cmap ); free( p_vout->p_sys->p_palette ); } /* Restore fb config */ ioctl( p_vout->p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info ); /* Close fb */ close( p_vout->p_sys->i_fd );}/***************************************************************************** * SwitchDisplay: VT change signal handler ***************************************************************************** * This function activates or deactivates the output of the thread. It is * called by the VT driver, on terminal change. *****************************************************************************/static void SwitchDisplay(int i_signal){#if 0 vout_thread_t *p_vout; vlc_mutex_lock( &p_vout_bank->lock ); /* XXX: only test the first video output */ if( p_vout_bank->i_count ) { p_vout = p_vout_bank->pp_vout[0]; switch( i_signal ) { case SIGUSR1: /* vt has been released */ p_vout->b_active = 0; ioctl( p_vout->p_sys->i_tty, VT_RELDISP, 1 ); break; case SIGUSR2: /* vt has been acquired */ p_vout->b_active = 1; ioctl( p_vout->p_sys->i_tty, VT_RELDISP, VT_ACTIVATE ); /* handle blanking */ vlc_mutex_lock( &p_vout->change_lock ); p_vout->i_changes |= VOUT_SIZE_CHANGE; vlc_mutex_unlock( &p_vout->change_lock ); break; } } vlc_mutex_unlock( &p_vout_bank->lock );#endif}/***************************************************************************** * TextMode and GfxMode : switch tty to text/graphic mode ***************************************************************************** * These functions toggle the tty mode. *****************************************************************************/static void TextMode( int i_tty ){ /* return to text mode */ if( -1 == ioctl(i_tty, KDSETMODE, KD_TEXT) ) { /*msg_Err( p_vout, "failed ioctl KDSETMODE KD_TEXT" );*/ }}static void GfxMode( int i_tty ){ /* switch to graphic mode */ if( -1 == ioctl(i_tty, KDSETMODE, KD_GRAPHICS) ) { /*msg_Err( p_vout, "failed ioctl KDSETMODE KD_GRAPHICS" );*/ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -