video_fb.c 10.7 KB
Newer Older
1 2
/******************************************************************************
 * vout_fb.c: Linux framebuffer video output display method
Vincent Seguin's avatar
Vincent Seguin committed
3
 * (c)1998 VideoLAN
4
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
5

6
/******************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
7
 * Preamble
8
 ******************************************************************************/
9

Vincent Seguin's avatar
Vincent Seguin committed
10
#include <errno.h>
11
#include <fcntl.h>
Vincent Seguin's avatar
Vincent Seguin committed
12 13 14
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
15 16 17 18
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
Vincent Seguin's avatar
Vincent Seguin committed
19
#include <sys/shm.h>
20
#include <sys/uio.h>                                        /* for input.h */
Vincent Seguin's avatar
Vincent Seguin committed
21 22 23 24 25 26 27 28 29 30 31

#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"

#include "input.h"
#include "video.h"
#include "video_output.h"
#include "video_sys.h"
#include "intf_msg.h"
32
#include "main.h"
Vincent Seguin's avatar
Vincent Seguin committed
33

34
/******************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
35
 * vout_sys_t: video output framebuffer method descriptor
36
 ******************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
37
 * This structure is part of the video output thread descriptor.
38 39
 * It describes the FB specific properties of an output thread.
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
40
typedef struct vout_sys_s
41
{
42
    /* System informations */
43 44
    int                         i_fb_dev;        /* framebuffer device handle */
    struct fb_var_screeninfo    var_info;    /* framebuffer mode informations */
Vincent Seguin's avatar
Vincent Seguin committed
45

46
    /* Video memory */
47 48
    byte_t *                    p_video;                       /* base adress */    
    size_t                      i_page_size;                     /* page size */
Vincent Seguin's avatar
Vincent Seguin committed
49 50
} vout_sys_t;

51
/******************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
52
 * Local prototypes
53
 ******************************************************************************/
54 55
static int     FBOpenDisplay   ( vout_thread_t *p_vout );
static void    FBCloseDisplay  ( vout_thread_t *p_vout );
56 57 58 59 60 61 62 63

/******************************************************************************
 * vout_SysCreate: allocates FB video thread output method
 ******************************************************************************
 * This function allocates and initializes a FB vout method.
 ******************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window )
{
64
    /* Allocate structure */
65
    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
66
    if( p_vout->p_sys == NULL )
67 68
    {   
        intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
69
        return( 1 );
Vincent Seguin's avatar
Vincent Seguin committed
70 71
    }

72 73 74
    /* Open and initialize device */
    if( FBOpenDisplay( p_vout ) )
    {
75
        intf_ErrMsg("vout error: can't open display\n");
76
        free( p_vout->p_sys );
77
        return( 1 );
78
    }
79

80
    return( 0 );
Vincent Seguin's avatar
Vincent Seguin committed
81 82
}

83 84 85
/******************************************************************************
 * vout_SysInit: initialize framebuffer video thread output method
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
86 87 88 89 90
int vout_SysInit( vout_thread_t *p_vout )
{
    return( 0 );
}

91 92 93
/******************************************************************************
 * vout_SysEnd: terminate FB video thread output method
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
94
void vout_SysEnd( vout_thread_t *p_vout )
95 96
{       
    ;    
Vincent Seguin's avatar
Vincent Seguin committed
97 98
}

99 100 101 102 103
/******************************************************************************
 * vout_SysDestroy: destroy FB video thread output method
 ******************************************************************************
 * Terminate an output method created by vout_FBCreateOutputMethod
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
104 105
void vout_SysDestroy( vout_thread_t *p_vout )
{
106
    FBCloseDisplay( p_vout );
Vincent Seguin's avatar
Vincent Seguin committed
107 108 109
    free( p_vout->p_sys );
}

110 111 112
/******************************************************************************
 * vout_SysManage: handle FB events
 ******************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
113
 * This function should be called regularly by video output thread. It manages
114
 * console events. It returns a non null value on error.
115
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
116 117
int vout_SysManage( vout_thread_t *p_vout )
{
118
    return 0;
Vincent Seguin's avatar
Vincent Seguin committed
119 120
}

121
/******************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
122
 * vout_SysDisplay: displays previously rendered output
123 124 125 126
 ******************************************************************************
 * This function send the currently rendered image to FB image, waits until
 * it is displayed and switch the two rendering buffers, preparing next frame.
 ******************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
127 128
void vout_SysDisplay( vout_thread_t *p_vout )
{
129
    /* tout est bien affich, on peut changer les 2 crans */
Sam Hocevar's avatar
Sam Hocevar committed
130
    p_vout->p_sys->var_info.xoffset = 0;
131
    p_vout->p_sys->var_info.yoffset = p_vout->i_buffer_index ? p_vout->p_sys->var_info.yres : 0;
132

Sam Hocevar's avatar
Sam Hocevar committed
133 134
    //ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );	
    ioctl( p_vout->p_sys->i_fb_dev, FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );	
Vincent Seguin's avatar
Vincent Seguin committed
135 136
}

137 138
/* following functions are local */

139
/******************************************************************************
140
 * FBOpenDisplay: open and initialize framebuffer device 
141
 ******************************************************************************
142 143 144
 * ?? The framebuffer mode is only provided as a fast and efficient way to
 * display video, providing the card is configured and the mode ok. It is
 * not portable, and is not supposed to work with many cards. Use at your
145 146 147
 * own risk !
 ******************************************************************************/

148 149 150 151 152 153
static int FBOpenDisplay( vout_thread_t *p_vout )
{
    char *psz_device;                               /* framebuffer device path */
    struct fb_fix_screeninfo    fix_info;       /* framebuffer fix information */

    /* Open framebuffer device */
154
    psz_device = main_GetPszVariable( VOUT_FB_DEV_VAR, VOUT_FB_DEV_DEFAULT );
155 156 157 158
    p_vout->p_sys->i_fb_dev = open( psz_device, O_RDWR);
    if( p_vout->p_sys->i_fb_dev == -1 )
    {
        intf_ErrMsg("vout error: can't open %s (%s)\n", psz_device, strerror(errno) );
159 160
        return( 1 );
    }
161 162 163 164 165

    // ?? here would be the code used to save the current mode and 
    // ?? change to the most appropriate mode...

    /* Get framebuffer device informations */
166 167
    if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
    {
168
        intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
169
        close( p_vout->p_sys->i_fb_dev );
170 171
        return( 1 );
    }
172 173

    /* Framebuffer must have some basic properties to be usable */
174
    //??
175

176
    /* Set some attributes */
177 178 179
    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;
Sam Hocevar's avatar
Sam Hocevar committed
180
    fprintf(stderr, "ypanstep is %i\n", fix_info.ypanstep);
181 182
    //??ask sam p_vout->p_sys->mode_info.sync = FB_SYNC_VERT_HIGH_ACT;
    //???
183
    if( ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
184 185
    {
        intf_ErrMsg("vout error: can't set framebuffer informations (%s)\n", strerror(errno) );
186 187
        close( p_vout->p_sys->i_fb_dev );
        return( 1 );
188 189 190 191
    }
    
    /* Get some informations again, in the definitive configuration */
    if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_FSCREENINFO, &fix_info ) ||
192
        ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
193 194 195
    {
        intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
        // ?? restore fb config
196
        close( p_vout->p_sys->i_fb_dev );
197 198
        return( 1 );
    }
199 200 201 202

    p_vout->i_width =                   p_vout->p_sys->var_info.xres;
    p_vout->i_height =                  p_vout->p_sys->var_info.yres;
    p_vout->i_screen_depth =            p_vout->p_sys->var_info.bits_per_pixel;
203 204
    switch( p_vout->i_screen_depth )
    {
205 206 207 208 209 210 211
    case 8:                                                          /* 8 bpp */
        p_vout->i_bytes_per_pixel = 1;
        p_vout->i_bytes_per_line = p_vout->i_width;
        break;

    case 15:                       /* 15 bpp (16bpp with a missing green bit) */
    case 16:                                         /* 16 bpp (65536 colors) */
212
        p_vout->i_bytes_per_pixel = 2;
213
        p_vout->i_bytes_per_line = p_vout->i_width * 2;
214 215
        break;

216
    case 24:                                   /* 24 bpp (millions of colors) */
217
        p_vout->i_bytes_per_pixel = 3;
218
        p_vout->i_bytes_per_line = p_vout->i_width * 3;
219
        break;
220

221
    case 32:                                   /* 32 bpp (millions of colors) */
222
        p_vout->i_bytes_per_pixel = 4;
223
        p_vout->i_bytes_per_line = p_vout->i_width * 4;
224 225
        break;

226
    default:                                      /* unsupported screen depth */
227
        intf_ErrMsg("vout error: screen depth %d is not supported\n",
228
		                     p_vout->i_screen_depth);
229 230 231
        return( 1  );
        break;
    }
232 233
    p_vout->p_sys->i_page_size = p_vout->p_sys->var_info.xres *
                p_vout->p_sys->var_info.yres * p_vout->i_bytes_per_pixel;
234 235

    /* Map two framebuffers a the very beginning of the fb */
236 237
    p_vout->p_sys->p_video = mmap(0, p_vout->p_sys->i_page_size * 2,
                                  PROT_READ | PROT_WRITE, MAP_SHARED,
238
                                  p_vout->p_sys->i_fb_dev, 0 );
239
    if( (int)p_vout->p_sys->p_video == -1 ) //?? according to man, it is -1. What about NULL ?
240 241 242 243
    {
        intf_ErrMsg("vout error: can't map video memory (%s)\n", strerror(errno) );
        // ?? restore fb config
        close( p_vout->p_sys->i_fb_dev );
244
        return( 1 );
245
    }
246 247

    /* Set and initialize buffers */
248 249
    vout_SetBuffers( p_vout, p_vout->p_sys->p_video, 
                     p_vout->p_sys->p_video + p_vout->p_sys->i_page_size );
250
    intf_DbgMsg("framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d\n",
251
                fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
252 253 254 255
    return( 0 );
}    

/******************************************************************************
256
 * FBCloseDisplay: close and reset framebuffer device 
257 258 259 260
 ******************************************************************************
 * Returns all resources allocated by FBOpenDisplay and restore the original
 * state of the device.
 ******************************************************************************/
261 262
static void FBCloseDisplay( vout_thread_t *p_vout )
{
263 264
    // Destroy window and close display
    close( p_vout->p_sys->i_fb_dev );    
265
}
266