1 /******************************************************************************
2 * vout_fb.c: Linux framebuffer video output display method
4 ******************************************************************************/
6 /******************************************************************************
8 ******************************************************************************/
17 #include <sys/ioctl.h>
20 #include <sys/uio.h> /* for input.h */
25 #include "vlc_thread.h"
29 #include "video_output.h"
30 #include "video_sys.h"
39 #define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
40 #define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
41 #define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
42 #define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
44 /******************************************************************************
45 * vout_sys_t: video output framebuffer method descriptor
46 ******************************************************************************
47 * This structure is part of the video output thread descriptor.
48 * It describes the FB specific properties of an output thread.
49 ******************************************************************************/
50 typedef struct vout_sys_s
52 /* System informations */
53 int i_fb_dev; /* framebuffer device handle */
54 struct fb_var_screeninfo var_info; /* framebuffer mode informations */
57 byte_t * p_video; /* base adress */
58 size_t i_page_size; /* page size */
60 struct fb_cmap fb_cmap; /* original colormap */
61 unsigned short *fb_palette; /* original palette */
65 /******************************************************************************
67 ******************************************************************************/
68 static int FBOpenDisplay ( vout_thread_t *p_vout );
69 static void FBCloseDisplay ( vout_thread_t *p_vout );
70 static void FBSetPalette ( p_vout_thread_t p_vout,
71 u16 *red, u16 *green, u16 *blue, u16 *transp );
73 /******************************************************************************
74 * vout_SysCreate: allocates FB video thread output method
75 ******************************************************************************
76 * This function allocates and initializes a FB vout method.
77 ******************************************************************************/
78 int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window )
80 /* Allocate structure */
81 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
82 if( p_vout->p_sys == NULL )
84 intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
88 /* Open and initialize device */
89 if( FBOpenDisplay( p_vout ) )
91 intf_ErrMsg("vout error: can't open display\n");
92 free( p_vout->p_sys );
99 /******************************************************************************
100 * vout_SysInit: initialize framebuffer video thread output method
101 ******************************************************************************/
102 int vout_SysInit( vout_thread_t *p_vout )
104 p_vout->p_set_palette = FBSetPalette;
108 /******************************************************************************
109 * vout_SysEnd: terminate FB video thread output method
110 ******************************************************************************/
111 void vout_SysEnd( vout_thread_t *p_vout )
116 /******************************************************************************
117 * vout_SysDestroy: destroy FB video thread output method
118 ******************************************************************************
119 * Terminate an output method created by vout_FBCreateOutputMethod
120 ******************************************************************************/
121 void vout_SysDestroy( vout_thread_t *p_vout )
123 FBCloseDisplay( p_vout );
124 free( p_vout->p_sys );
127 /******************************************************************************
128 * vout_SysManage: handle FB events
129 ******************************************************************************
130 * This function should be called regularly by video output thread. It manages
131 * console events. It returns a non null value on error.
132 ******************************************************************************/
133 int vout_SysManage( vout_thread_t *p_vout )
138 /******************************************************************************
139 * vout_SysDisplay: displays previously rendered output
140 ******************************************************************************
141 * This function send the currently rendered image to FB image, waits until
142 * it is displayed and switch the two rendering buffers, preparing next frame.
143 ******************************************************************************/
144 void vout_SysDisplay( vout_thread_t *p_vout )
146 /* tout est bien affiché, on peut échanger les 2 écrans */
147 p_vout->p_sys->var_info.xoffset = 0;
148 p_vout->p_sys->var_info.yoffset = p_vout->i_buffer_index ? p_vout->p_sys->var_info.yres : 0;
150 //ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
151 ioctl( p_vout->p_sys->i_fb_dev, FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );
154 /* following functions are local */
156 /******************************************************************************
157 * FBOpenDisplay: open and initialize framebuffer device
158 ******************************************************************************
159 * ?? The framebuffer mode is only provided as a fast and efficient way to
160 * display video, providing the card is configured and the mode ok. It is
161 * not portable, and is not supposed to work with many cards. Use at your
163 ******************************************************************************/
165 static int FBOpenDisplay( vout_thread_t *p_vout )
167 char *psz_device; /* framebuffer device path */
168 struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
169 /* framebuffer palette information */
170 /* Open framebuffer device */
171 psz_device = main_GetPszVariable( VOUT_FB_DEV_VAR, VOUT_FB_DEV_DEFAULT );
172 p_vout->p_sys->i_fb_dev = open( psz_device, O_RDWR);
173 if( p_vout->p_sys->i_fb_dev == -1 )
175 intf_ErrMsg("vout error: can't open %s (%s)\n", psz_device, strerror(errno) );
179 // ?? here would be the code used to save the current mode and
180 // ?? change to the most appropriate mode...
182 /* Get framebuffer device informations */
183 if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
185 intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
186 close( p_vout->p_sys->i_fb_dev );
190 /* Framebuffer must have some basic properties to be usable */
193 /* Set some attributes */
194 p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN;
195 p_vout->p_sys->var_info.xoffset = 0;
196 p_vout->p_sys->var_info.yoffset = 0;
197 fprintf(stderr, "ypanstep is %i\n", fix_info.ypanstep);
198 //??ask sam p_vout->p_sys->mode_info.sync = FB_SYNC_VERT_HIGH_ACT;
200 if( ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
202 intf_ErrMsg("vout error: can't set framebuffer informations (%s)\n", strerror(errno) );
203 close( p_vout->p_sys->i_fb_dev );
207 /* Get some informations again, in the definitive configuration */
208 if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_FSCREENINFO, &fix_info ) ||
209 ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
211 intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
212 // ?? restore fb config
213 close( p_vout->p_sys->i_fb_dev );
217 p_vout->i_width = p_vout->p_sys->var_info.xres;
218 p_vout->i_height = p_vout->p_sys->var_info.yres;
219 p_vout->i_screen_depth = p_vout->p_sys->var_info.bits_per_pixel;
220 switch( p_vout->i_screen_depth )
223 p_vout->p_sys->fb_palette = malloc( 8 * 256 * sizeof(unsigned short) );
224 p_vout->p_sys->fb_cmap.start = 0;
225 p_vout->p_sys->fb_cmap.len = 256;
226 p_vout->p_sys->fb_cmap.red = p_vout->p_sys->fb_palette;
227 p_vout->p_sys->fb_cmap.green = p_vout->p_sys->fb_palette + 256 * sizeof(unsigned short);
228 p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->fb_palette + 2 * 256 * sizeof(unsigned short);
229 p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->fb_palette + 3 * 256 * sizeof(unsigned short);
231 ioctl( p_vout->p_sys->i_fb_dev, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
233 /* initializes black & white palette */
234 //FBInitRGBPalette( p_vout );
235 //FBInitBWPalette( p_vout );
237 p_vout->i_bytes_per_pixel = 1;
238 p_vout->i_bytes_per_line = p_vout->i_width;
241 case 15: /* 15 bpp (16bpp with a missing green bit) */
242 case 16: /* 16 bpp (65536 colors) */
243 p_vout->i_bytes_per_pixel = 2;
244 p_vout->i_bytes_per_line = p_vout->i_width * 2;
247 case 24: /* 24 bpp (millions of colors) */
248 p_vout->i_bytes_per_pixel = 3;
249 p_vout->i_bytes_per_line = p_vout->i_width * 3;
252 case 32: /* 32 bpp (millions of colors) */
253 p_vout->i_bytes_per_pixel = 4;
254 p_vout->i_bytes_per_line = p_vout->i_width * 4;
257 default: /* unsupported screen depth */
258 intf_ErrMsg("vout error: screen depth %d is not supported\n",
259 p_vout->i_screen_depth);
263 p_vout->p_sys->i_page_size = p_vout->p_sys->var_info.xres *
264 p_vout->p_sys->var_info.yres * p_vout->i_bytes_per_pixel;
266 /* Map two framebuffers a the very beginning of the fb */
267 p_vout->p_sys->p_video = mmap(0, p_vout->p_sys->i_page_size * 2,
268 PROT_READ | PROT_WRITE, MAP_SHARED,
269 p_vout->p_sys->i_fb_dev, 0 );
270 if( (int)p_vout->p_sys->p_video == -1 ) //?? according to man, it is -1. What about NULL ?
272 intf_ErrMsg("vout error: can't map video memory (%s)\n", strerror(errno) );
273 // ?? restore fb config
274 close( p_vout->p_sys->i_fb_dev );
278 /* Set and initialize buffers */
279 vout_SetBuffers( p_vout, p_vout->p_sys->p_video,
280 p_vout->p_sys->p_video + p_vout->p_sys->i_page_size );
281 intf_DbgMsg("framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d\n",
282 fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
286 /******************************************************************************
287 * FBCloseDisplay: close and reset framebuffer device
288 ******************************************************************************
289 * Returns all resources allocated by FBOpenDisplay and restore the original
290 * state of the device.
291 ******************************************************************************/
292 static void FBCloseDisplay( vout_thread_t *p_vout )
294 /* Restore palette */
295 if( p_vout->i_screen_depth == 8 );
297 ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &p_vout->p_sys->fb_cmap );
298 free( p_vout->p_sys->fb_palette );
301 // Destroy window and close display
302 close( p_vout->p_sys->i_fb_dev );
305 /******************************************************************************
306 * FBSetPalette: sets an 8 bpp palette
307 ******************************************************************************
308 * This function is just a prototype that does nothing. Architectures that
309 * support palette allocation should override it.
310 ******************************************************************************/
311 static void FBSetPalette ( p_vout_thread_t p_vout,
312 u16 *red, u16 *green, u16 *blue, u16 *transp )
314 struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
315 ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );