📄 fb.c
字号:
/* * 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( !p_vout->p_sys->b_hw_accel ) { vlc_memcpy( p_vout->p_sys->p_video, p_pic->p->p_pixels, p_vout->p_sys->i_page_size ); }}#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 ){ vout_sys_t *p_sys = (vout_sys_t *) p_vout->p_sys; 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_sys->i_fd = open( psz_device, O_RDWR); if( p_sys->i_fd == -1 ) { msg_Err( p_vout, "cannot open %s (%m)", psz_device ); free( psz_device ); return VLC_EGENERIC; } free( psz_device ); psz_device = NULL; /* Get framebuffer device information */ if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) ) { msg_Err( p_vout, "cannot get fb info (%m)" ); close( p_sys->i_fd ); return VLC_EGENERIC; } memcpy( &p_sys->old_info, &p_sys->var_info, sizeof( struct fb_var_screeninfo ) ); /* Get some info on the framebuffer itself */ if( !p_sys->b_auto ) { p_sys->var_info.xres = p_sys->var_info.xres_virtual = p_sys->i_width; p_sys->var_info.yres = p_sys->var_info.yres_virtual = p_sys->i_height; p_vout->fmt_out.i_width = p_sys->i_width; p_vout->fmt_out.i_height = p_sys->i_height; } /* Set some attributes */ p_sys->var_info.activate = p_sys->b_tty ? FB_ACTIVATE_NXTOPEN : FB_ACTIVATE_NOW; p_sys->var_info.xoffset = 0; p_sys->var_info.yoffset = 0; if( ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->var_info ) ) { msg_Err( p_vout, "cannot set fb info (%m)" ); close( p_sys->i_fd ); return VLC_EGENERIC; } /* Get some information again, in the definitive configuration */ if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) || ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) ) { msg_Err( p_vout, "cannot get additional fb info (%m)" ); /* Restore fb config */ ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info ); close( p_sys->i_fd ); return VLC_EGENERIC; } /* If the fb has limitations on mode change, * then keep the resolution of the fb */ if( (p_sys->i_height != p_sys->var_info.yres) || (p_sys->i_width != p_sys->var_info.xres) ) { p_sys->b_auto = true; msg_Warn( p_vout, "using framebuffer native resolution instead of requested (%ix%i)", p_sys->i_width, p_sys->i_height ); } p_sys->i_height = p_sys->var_info.yres; p_sys->i_width = p_sys->var_info.xres_virtual ? p_sys->var_info.xres_virtual : p_sys->var_info.xres; /* 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) (request %ix%i)", p_sys->var_info.xres, p_sys->var_info.yres, p_sys->var_info.xres_virtual, p_sys->var_info.yres_virtual, p_sys->i_width, p_sys->i_height ); p_sys->p_palette = NULL; p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep ); switch( p_sys->var_info.bits_per_pixel ) { case 8: p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) ); if( !p_sys->p_palette ) { /* Restore fb config */ ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info ); close( p_sys->i_fd ); return VLC_ENOMEM; } p_sys->fb_cmap.start = 0; p_sys->fb_cmap.len = 256; p_sys->fb_cmap.red = p_sys->p_palette; p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t ); p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t ); p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t ); /* Save the colormap */ ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap ); p_sys->i_bytes_per_pixel = 1; break; case 15: case 16: p_sys->i_bytes_per_pixel = 2; break; case 24: p_sys->i_bytes_per_pixel = 3; break; case 32: p_sys->i_bytes_per_pixel = 4; break; default: msg_Err( p_vout, "screen depth %d is not supported", p_sys->var_info.bits_per_pixel ); /* Restore fb config */ ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_sys->old_info ); close( p_sys->i_fd ); return VLC_EGENERIC; } p_sys->i_page_size = p_sys->i_width * p_sys->i_height * p_sys->i_bytes_per_pixel; /* Map a framebuffer at the beginning */ p_sys->p_video = mmap( 0, p_sys->i_page_size, PROT_READ | PROT_WRITE, MAP_SHARED, p_sys->i_fd, 0 ); if( p_sys->p_video == ((void*)-1) ) { msg_Err( p_vout, "cannot map video memory (%m)" ); if( p_sys->var_info.bits_per_pixel == 8 ) { free( p_sys->p_palette ); p_sys->p_palette = NULL; } /* Restore fb config */ ioctl( p_sys->i_fd, FBIOPUT_VSCREENINFO, &p_vout->p_sys->old_info ); close( 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 ); p_vout->p_sys->p_palette = NULL; } /* 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_sys->i_tty, VT_RELDISP, 1 ); break; case SIGUSR2: /* vt has been acquired */ p_vout->b_active = 1; ioctl( 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 + -