Commit 89a64c61 authored by Sam Hocevar's avatar Sam Hocevar

. fix� une erreur de syntaxe dans video_fb.c

 . *3dfx* devient *glide*
 . suppression de tabulations dans quelques fichiers
 . suppression des 2 warnings dans sam_synchro
 . video_* devient vout_* quand ce sont des m�thodes de vout
 . tentative de correction de la d�tection de MMX pour BeOS
 . nouvelle option vlc_vout_method (faute de mieux pour le moment)
 . modification du Makefile pour supporter plusieurs VIDEO_*

dor�navant on peut compiler plusieurs output diff�rents dans le
client. la pr�f�rence se fait dans l'ordre x11, fb, ggi, glide...

si on le compile avec x11 et fb, par d�faut il se lancera en X.
pour le lancer en framebuffer :
./vlc vlc_vout_method=fb

(il faut que je proprifie un peu le choix de l'output, et que je
facilite l'ajout d'un nouveau vout_*)
parent ce722764
......@@ -14,17 +14,16 @@
#SHELL=/bin/sh
# Video output settings
VIDEO=X11
#VIDEO=DUMMY
#VIDEO=FB
#VIDEO=GGI
VIDEO_X11=YES
VIDEO_FB=YES
#VIDEO_GGI=YES
# Highly experimental
#VIDEO=3DFX
#VIDEO_GLIDE=YES
# Not yet supported
#VIDEO=BEOS
#VIDEO=DGA
#VIDEO_BEOS=YES
#VIDEO_DGA=YES
# Target architecture
ARCH=X86
......@@ -56,8 +55,49 @@ DEBUG=1
# Program version - may only be changed by the project leader
PROGRAM_VERSION = 1.0-dev
# VIDEO_OPTIONS describes all used video options
VIDEO_OPTIONS = dummy
intf_method = interface/intf_dummy.o
vout_method = video_output/vout_dummy.o
ifeq ($(VIDEO_GLIDE), YES)
VIDEO_OPTIONS += glide
DEFINE += -DVIDEO_GLIDE
intf_method += interface/intf_glide.o
vout_method += video_output/vout_glide.o
endif
ifeq ($(VIDEO_X11), YES)
VIDEO_OPTIONS += x11
DEFINE += -DVIDEO_X11
intf_method += interface/intf_x11.o
vout_method += video_output/vout_x11.o
endif
ifeq ($(VIDEO_GGI), YES)
VIDEO_OPTIONS += ggi
DEFINE += -DVIDEO_GGI
intf_method += interface/intf_ggi.o
vout_method += video_output/vout_ggi.o
endif
ifeq ($(VIDEO_FB), YES)
VIDEO_OPTIONS += fb
DEFINE += -DVIDEO_FB
intf_method += interface/intf_fb.o
vout_method += video_output/vout_fb.o
endif
ifeq ($(VIDEO_BEOS), YES)
VIDEO_OPTIONS += beos
DEFINE += -DVIDEO_BEOS
intf_method += interface/intf_beos.o
vout_method += video_output/vout_beos.o
endif
ifeq ($(VIDEO_DGA), YES)
VIDEO_OPTIONS += dga
DEFINE += -DVIDEO_DGA
intf_method += interface/intf_dga.o
vout_method += video_output/vout_dga.o
endif
# PROGRAM_OPTIONS is an identification string of the compilation options
PROGRAM_OPTIONS = $(VIDEO) $(ARCH) $(SYS)
PROGRAM_OPTIONS = $(ARCH) $(SYS)
ifeq ($(DEBUG),1)
PROGRAM_OPTIONS += DEBUG
endif
......@@ -66,10 +106,10 @@ endif
PROGRAM_BUILD = `date -R` $(USER)@`hostname`
# DEFINE will contain some of the constants definitions decided in Makefile,
# including VIDEO_xx and ARCH_xx. It will be passed to C compiler.
DEFINE += -DVIDEO_$(VIDEO)
# including ARCH_xx and SYS_xx. It will be passed to C compiler.
DEFINE += -DARCH_$(ARCH)
DEFINE += -DSYS_$(SYS)
DEFINE += -DVIDEO_OPTIONS="\"$(VIDEO_OPTIONS)\""
DEFINE += -DPROGRAM_VERSION="\"$(PROGRAM_VERSION)\""
DEFINE += -DPROGRAM_OPTIONS="\"$(PROGRAM_OPTIONS)\""
DEFINE += -DPROGRAM_BUILD="\"$(PROGRAM_BUILD)\""
......@@ -81,7 +121,7 @@ endif
video = $(shell echo $(VIDEO) | tr 'A-Z' 'a-z')
################################################################################
# Tunning and other variables - do not change anything except if you know
# Tuning and other variables - do not change anything except if you know
# exactly what you are doing
################################################################################
......@@ -90,11 +130,11 @@ video = $(shell echo $(VIDEO) | tr 'A-Z' 'a-z')
#
INCLUDE += -Iinclude
ifeq ($(VIDEO),X11)
ifeq ($(VIDEO_X11),YES)
INCLUDE += -I/usr/X11R6/include
endif
ifeq ($(VIDEO),3DFX)
ifeq ($(VIDEO_GLIDE),YES)
INCLUDE += -I/usr/include/glide
endif
......@@ -104,15 +144,15 @@ endif
LIB += -lpthread
LIN += -lm
ifeq ($(VIDEO),X11)
ifeq ($(VIDEO_X11),YES)
LIB += -L/usr/X11R6/lib
LIB += -lX11
LIB += -lXext
endif
ifeq ($(VIDEO),GGI)
ifeq ($(VIDEO_GGI),YES)
LIB += -lggi
endif
ifeq ($(VIDEO),3DFX)
ifeq ($(VIDEO_GLIDE),YES)
LIB += -lglide2x
endif
......@@ -194,7 +234,7 @@ interface_obj = interface/main.o \
interface/intf_ctrl.o \
interface/control.o \
interface/intf_console.o \
interface/intf_$(video).o
$(intf_method)
input_obj = input/input_vlan.o \
input/input_file.o \
......@@ -209,9 +249,9 @@ audio_output_obj = audio_output/audio_output.o \
audio_output/audio_dsp.o
video_output_obj = video_output/video_output.o \
video_output/video_$(video).o \
video_output/video_text.o \
video_output/video_yuv.o
video_output/video_yuv.o \
$(vout_method)
ac3_decoder_obj = ac3_decoder/ac3_decoder.o \
ac3_decoder/ac3_parse.o \
......
......@@ -226,6 +226,9 @@
* Default settings for video output threads
*/
/* Environment variable containing the display method */
#define VOUT_METHOD_VAR "vlc_vout_method"
/* Environment variable used in place of DISPLAY if available */
#define VOUT_DISPLAY_VAR "vlc_display"
......
......@@ -20,7 +20,8 @@
#ifdef DEBUG
#define ASSERT(p_Mem) \
if (!(p_Mem)) \
intf_ErrMsg("Void pointer error: %s line %d (variable %s at address %p)\n", \
intf_ErrMsg("Void pointer error: " \
"%s line %d (variable %s at address %p)\n", \
__FILE__, __LINE__, #p_Mem, &p_Mem);
#else
......
......@@ -26,6 +26,10 @@
* This structe describes all interface-specific data of the main (interface)
* thread.
*****************************************************************************/
typedef int ( intf_sys_create_t ) ( p_intf_thread_t p_intf );
typedef void ( intf_sys_destroy_t ) ( p_intf_thread_t p_intf );
typedef void ( intf_sys_manage_t ) ( p_intf_thread_t p_intf );
typedef struct intf_thread_s
{
boolean_t b_die; /* `die' flag */
......@@ -34,12 +38,18 @@ typedef struct intf_thread_s
p_intf_console_t p_console; /* console */
p_intf_sys_t p_sys; /* system interface */
/* method-specific functions */
intf_sys_create_t * p_sys_create; /* create interface thread */
intf_sys_manage_t * p_sys_manage; /* main loop */
intf_sys_destroy_t * p_sys_destroy; /* destroy interface */
/* Channels array - NULL if not used */
p_intf_channel_t p_channel; /* description of channels */
/* Main threads - NULL if not active */
p_vout_thread_t p_vout;
p_input_thread_t p_input;
} intf_thread_t;
/*****************************************************************************
......
......@@ -6,6 +6,37 @@
/*****************************************************************************
* Prototypes
*****************************************************************************/
int intf_SysCreate ( p_intf_thread_t p_intf );
void intf_SysDestroy( p_intf_thread_t p_intf );
void intf_SysManage ( p_intf_thread_t p_intf );
int intf_DummySysCreate ( p_intf_thread_t p_intf );
void intf_DummySysDestroy ( p_intf_thread_t p_intf );
void intf_DummySysManage ( p_intf_thread_t p_intf );
#ifdef VIDEO_X11
int intf_X11SysCreate ( p_intf_thread_t p_intf );
void intf_X11SysDestroy ( p_intf_thread_t p_intf );
void intf_X11SysManage ( p_intf_thread_t p_intf );
#endif
#ifdef VIDEO_FB
int intf_FBSysCreate ( p_intf_thread_t p_intf );
void intf_FBSysDestroy ( p_intf_thread_t p_intf );
void intf_FBSysManage ( p_intf_thread_t p_intf );
#endif
#ifdef VIDEO_GLIDE
int intf_GlideSysCreate ( p_intf_thread_t p_intf );
void intf_GlideSysDestroy ( p_intf_thread_t p_intf );
void intf_GlideSysManage ( p_intf_thread_t p_intf );
#endif
#ifdef VIDEO_DGA
int intf_DGASysCreate ( p_intf_thread_t p_intf );
void intf_DGASysDestroy ( p_intf_thread_t p_intf );
void intf_DGASysManage ( p_intf_thread_t p_intf );
#endif
#ifdef VIDEO_GGI
int intf_GGISysCreate ( p_intf_thread_t p_intf );
void intf_GGISysDestroy ( p_intf_thread_t p_intf );
void intf_GGISysManage ( p_intf_thread_t p_intf );
#endif
#ifdef VIDEO_BEOS
int intf_BeSysCreate ( p_intf_thread_t p_intf );
void intf_BeSysDestroy ( p_intf_thread_t p_intf );
void intf_BeSysManage ( p_intf_thread_t p_intf );
#endif
......@@ -61,7 +61,7 @@ typedef struct vout_yuv_s
* vout_buffer_t: rendering buffer
*****************************************************************************
* This structure store informations about a buffer. Buffers are not completely
* cleared between displays, and modified areas needs to be stored.
* cleared between displays, and modified areas need to be stored.
*****************************************************************************/
typedef struct vout_buffer_s
{
......@@ -82,11 +82,18 @@ typedef struct vout_buffer_s
* vout_thread_t: video output thread descriptor
*****************************************************************************
* Any independant video output device, such as an X11 window or a GGI device,
* is represented by a video output thread, and described using following
* is represented by a video output thread, and described using the following
* structure.
*****************************************************************************/
typedef void (vout_set_palette_t)( p_vout_thread_t p_vout,
u16 *red, u16 *green, u16 *blue, u16 *transp );
typedef int (vout_sys_create_t) ( p_vout_thread_t p_vout,
char *psz_display, int i_root_window );
typedef int (vout_sys_init_t) ( p_vout_thread_t p_vout );
typedef void (vout_sys_end_t) ( p_vout_thread_t p_vout );
typedef void (vout_sys_destroy_t) ( p_vout_thread_t p_vout );
typedef int (vout_sys_manage_t) ( p_vout_thread_t p_vout );
typedef void (vout_sys_display_t) ( p_vout_thread_t p_vout );
typedef void (vout_set_palette_t) ( p_vout_thread_t p_vout, u16 *red,
u16 *green, u16 *blue, u16 *transp );
typedef struct vout_thread_s
{
......@@ -100,6 +107,7 @@ typedef struct vout_thread_s
vlc_mutex_t change_lock; /* thread change lock */
int * pi_status; /* temporary status flag */
p_vout_sys_t p_sys; /* system output method */
int i_method; /* display method */
/* Current display properties */
u16 i_changes; /* changes made to the thread */
......@@ -127,12 +135,20 @@ typedef struct vout_thread_s
u32 i_gray_pixel; /* gray */
u32 i_blue_pixel; /* blue */
/* method-dependant functions */
vout_sys_create_t * p_sys_create; /* allocate output method */
vout_sys_init_t * p_sys_init; /* initialize output method */
vout_sys_end_t * p_sys_end; /* terminate output method */
vout_sys_destroy_t * p_sys_destroy; /* destroy output method */
vout_sys_manage_t * p_sys_manage; /* handle events */
vout_sys_display_t * p_sys_display; /* display rendered image */
vout_set_palette_t * p_set_palette; /* sets 8bpp palette */
/* Pictures and rendering properties */
boolean_t b_grayscale; /* color or grayscale display */
boolean_t b_info; /* print additionnal informations */
boolean_t b_interface; /* render interface */
boolean_t b_scale; /* allow picture scaling */
vout_set_palette_t *p_set_palette; /* sets 8bpp palette */
/* Idle screens management */
mtime_t last_display_date; /* last non idle display date */
......@@ -158,8 +174,45 @@ typedef struct vout_thread_s
/* Bitmap fonts */
p_vout_font_t p_default_font; /* default font */
p_vout_font_t p_large_font; /* large font */
} vout_thread_t;
/* Output methods */
#define VOUT_DUMMY_METHOD 0x0000 /* dummy video output */
#define VOUT_X11_METHOD 0x0001 /* X11 */
#define VOUT_GGI_METHOD 0x0002 /* General Graphics Interface */
#define VOUT_FB_METHOD 0x0003 /* Linux framebuffer */
#define VOUT_GLIDE_METHOD 0x0004 /* Voodoo 3dfx */
#define VOUT_DGA_METHOD 0x0005 /* X11 DGA extension */
#define VOUT_BEOS_METHOD 0x0006 /* BeOS rendering */
/* Get the fallback method */
#ifdef VIDEO_X11
#define VOUT_DEFAULT_METHOD "x11"
#else
#ifdef VIDEO_FB
#define VOUT_DEFAULT_METHOD "fb"
#else
#ifdef VIDEO_GGI
#define VOUT_DEFAULT_METHOD "ggi"
#else
#ifdef VIDEO_GLIDE
#define VOUT_DEFAULT_METHOD "glide"
#else
#ifdef VIDEO_DGA
#define VOUT_DEFAULT_METHOD "dga"
#else
#ifdef VIDEO_BEOS
#define VOUT_DEFAULT_METHOD "beos"
#else
#define VOUT_DEFAULT_METHOD "dummy"
#endif
#endif
#endif
#endif
#endif
#endif
/* Flags for changes - these flags are set in the i_changes field when another
* thread changed a variable */
#define VOUT_INFO_CHANGE 0x0001 /* b_info changed */
......@@ -187,7 +240,7 @@ typedef struct vout_thread_s
* Prototypes
*****************************************************************************/
vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window,
int i_width, int i_height, int *pi_status );
int i_width, int i_height, int *pi_status, int i_method );
void vout_DestroyThread ( vout_thread_t *p_vout, int *pi_status );
picture_t * vout_CreatePicture ( vout_thread_t *p_vout, int i_type,
int i_width, int i_height );
......
......@@ -6,12 +6,58 @@
/*****************************************************************************
* Prototypes
*****************************************************************************/
int vout_SysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_SysInit ( p_vout_thread_t p_vout );
void vout_SysEnd ( p_vout_thread_t p_vout );
void vout_SysDestroy ( p_vout_thread_t p_vout );
int vout_SysManage ( p_vout_thread_t p_vout );
void vout_SysDisplay ( p_vout_thread_t p_vout );
int vout_DummySysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_DummySysInit ( p_vout_thread_t p_vout );
void vout_DummySysEnd ( p_vout_thread_t p_vout );
void vout_DummySysDestroy ( p_vout_thread_t p_vout );
int vout_DummySysManage ( p_vout_thread_t p_vout );
void vout_DummySysDisplay ( p_vout_thread_t p_vout );
#ifdef VIDEO_X11
int vout_X11SysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_X11SysInit ( p_vout_thread_t p_vout );
void vout_X11SysEnd ( p_vout_thread_t p_vout );
void vout_X11SysDestroy ( p_vout_thread_t p_vout );
int vout_X11SysManage ( p_vout_thread_t p_vout );
void vout_X11SysDisplay ( p_vout_thread_t p_vout );
#endif
#ifdef VIDEO_FB
int vout_FBSysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_FBSysInit ( p_vout_thread_t p_vout );
void vout_FBSysEnd ( p_vout_thread_t p_vout );
void vout_FBSysDestroy ( p_vout_thread_t p_vout );
int vout_FBSysManage ( p_vout_thread_t p_vout );
void vout_FBSysDisplay ( p_vout_thread_t p_vout );
#endif
#ifdef VIDEO_GLIDE
int vout_GlideSysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_GlideSysInit ( p_vout_thread_t p_vout );
void vout_GlideSysEnd ( p_vout_thread_t p_vout );
void vout_GlideSysDestroy ( p_vout_thread_t p_vout );
int vout_GlideSysManage ( p_vout_thread_t p_vout );
void vout_GlideSysDisplay ( p_vout_thread_t p_vout );
#endif
#ifdef VIDEO_DGA
int vout_DGASysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_DGASysInit ( p_vout_thread_t p_vout );
void vout_DGASysEnd ( p_vout_thread_t p_vout );
void vout_DGASysDestroy ( p_vout_thread_t p_vout );
int vout_DGASysManage ( p_vout_thread_t p_vout );
void vout_DGASysDisplay ( p_vout_thread_t p_vout );
#endif
#ifdef VIDEO_GGI
int vout_GGISysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_GGISysInit ( p_vout_thread_t p_vout );
void vout_GGISysEnd ( p_vout_thread_t p_vout );
void vout_GGISysDestroy ( p_vout_thread_t p_vout );
int vout_GGISysManage ( p_vout_thread_t p_vout );
void vout_GGISysDisplay ( p_vout_thread_t p_vout );
#endif
#ifdef VIDEO_BEOS
int vout_BeSysCreate ( p_vout_thread_t p_vout, char *psz_display, int i_root_window );
int vout_BeSysInit ( p_vout_thread_t p_vout );
void vout_BeSysEnd ( p_vout_thread_t p_vout );
void vout_BeSysDestroy ( p_vout_thread_t p_vout );
int vout_BeSysManage ( p_vout_thread_t p_vout );
void vout_BeSysDisplay ( p_vout_thread_t p_vout );
#endif
......@@ -68,6 +68,7 @@ static int ParseChannel ( intf_channel_t *p_channel, char *psz_str );
intf_thread_t* intf_Create( void )
{
intf_thread_t *p_intf;
char * psz_method;
/* Allocate structure */
p_intf = malloc( sizeof( intf_thread_t ) );
......@@ -77,6 +78,70 @@ intf_thread_t* intf_Create( void )
return( NULL );
}
/* initialize method-dependent functions */
psz_method = main_GetPszVariable( VOUT_METHOD_VAR, VOUT_DEFAULT_METHOD );
if( !strcmp(psz_method, "dummy") )
{
p_intf->p_sys_create = intf_DummySysCreate;
p_intf->p_sys_manage = intf_DummySysManage;
p_intf->p_sys_destroy = intf_DummySysDestroy;
}
#ifdef VIDEO_X11
else if( !strcmp(psz_method, "x11") )
{
p_intf->p_sys_create = intf_X11SysCreate;
p_intf->p_sys_manage = intf_X11SysManage;
p_intf->p_sys_destroy = intf_X11SysDestroy;
}
#endif
#ifdef VIDEO_FB
else if( !strcmp(psz_method, "fb") )
{
p_intf->p_sys_create = intf_FBSysCreate;
p_intf->p_sys_manage = intf_FBSysManage;
p_intf->p_sys_destroy = intf_FBSysDestroy;
}
#endif
#ifdef VIDEO_GGI
else if( !strcmp(psz_method, "ggi") )
{
p_intf->p_sys_create = intf_GGISysCreate;
p_intf->p_sys_manage = intf_GGISysManage;
p_intf->p_sys_destroy = intf_GGISysDestroy;
}
#endif
#ifdef VIDEO_DGA
else if( !strcmp(psz_method, "dga") )
{
p_intf->p_sys_create = intf_DGASysCreate;
p_intf->p_sys_manage = intf_DGASysManage;
p_intf->p_sys_destroy = intf_DGASysDestroy;
}
#endif
#ifdef VIDEO_GLIDE
else if( !strcmp(psz_method, "glide") )
{
p_intf->p_sys_create = intf_GlideSysCreate;
p_intf->p_sys_manage = intf_GlideSysManage;
p_intf->p_sys_destroy = intf_GlideSysDestroy;
}
#endif
#ifdef VIDEO_BEOS
else if( !strcmp(psz_method, "beos") )
{
p_intf->p_sys_create = intf_BeSysCreate;
p_intf->p_sys_manage = intf_BeSysManage;
p_intf->p_sys_destroy = intf_BeSysDestroy;
}
#endif
else
{
intf_ErrMsg( "error: video output method not available\n" );
free( p_intf );
return( NULL );
}
/* Initialize structure */
p_intf->b_die = 0;
p_intf->p_vout = NULL;
......@@ -95,7 +160,7 @@ intf_thread_t* intf_Create( void )
free( p_intf );
return( NULL );
}
if( intf_SysCreate( p_intf ) )
if( p_intf->p_sys_create( p_intf ) )
{
intf_ErrMsg("error: can't create interface\n");
intf_ConsoleDestroy( p_intf->p_console );
......@@ -128,7 +193,7 @@ void intf_Run( intf_thread_t *p_intf )
intf_FlushMsg();
/* Manage specific interface */
intf_SysManage( p_intf );
p_intf->p_sys_manage( p_intf );
/* Check attached threads status */
if( (p_intf->p_vout != NULL) && p_intf->p_vout->b_error )
......@@ -157,7 +222,7 @@ void intf_Run( intf_thread_t *p_intf )
void intf_Destroy( intf_thread_t *p_intf )
{
/* Destroy interfaces */
intf_SysDestroy( p_intf );
p_intf->p_sys_destroy( p_intf );
intf_ConsoleDestroy( p_intf->p_console );
/* Unload channels */
......
/*****************************************************************************
* intf_3dfx.c: 3dfx interface
* (c)2000 VideoLAN
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <signal.h>
#include <stdio.h> /* stderr */
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h> /* close() */
#include <sys/uio.h> /* for input.h */
#include <linutil.h> /* Glide kbhit() and getch() */
#include <sys/types.h> /* open() */
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "input.h"
#include "video.h"
#include "video_output.h"
#include "intf_sys.h"
#include "intf_msg.h"
#include "interface.h"
#include "main.h"
/*****************************************************************************
* intf_sys_t: description and status of 3dfx interface
*****************************************************************************/
typedef struct intf_sys_s
{
} intf_sys_t;
/*****************************************************************************
* intf_SysCreate: initialize 3dfx interface
*****************************************************************************/
int intf_SysCreate( intf_thread_t *p_intf )
{
/* Allocate instance and initialize some members */
p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
if( p_intf->p_sys == NULL )
{
return( 1 );
};
intf_DbgMsg("0x%x\n", p_intf );
/* Spawn video output thread */
if( p_main->b_video )
{
p_intf->p_vout = vout_CreateThread( NULL, 0, 0, 0, NULL);
if( p_intf->p_vout == NULL ) /* error */
{
intf_ErrMsg("intf error: can't create output thread\n" );
return( 1 );
}
}
return( 0 );
}
/*****************************************************************************
* intf_SysDestroy: destroy 3dfx interface
*****************************************************************************/
void intf_SysDestroy( intf_thread_t *p_intf )
{
/* Close input thread, if any (blocking) */
if( p_intf->p_input )
{
input_DestroyThread( p_intf->p_input, NULL );
}
/* Close video output thread, if any (blocking) */
if( p_intf->p_vout )
{
vout_DestroyThread( p_intf->p_vout, NULL );
}
/* Destroy structure */
free( p_intf->p_sys );
}
/*****************************************************************************
* intf_SysManage: event loop
*****************************************************************************/
void intf_SysManage( intf_thread_t *p_intf )
{
unsigned int buf;
/* very Linux specific - see tlib.c in Glide for other versions */
while( kbhit() )
{
if( intf_ProcessKey(p_intf, (int)buf = getch()) )
{
printf("unhandled key '%c' (%i)\n", (char) buf, buf );
}
}
}
......@@ -107,7 +107,7 @@ static int TestMMX ( void );
* -openning of audio output device and some global modules
* -execution of interface, which exit on error or on user request
* -closing of audio output device and some global modules
* On error, the spawned threads are cancelled, and the openned devices closed.
* On error, the spawned threads are cancelled, and the open devices closed.
*****************************************************************************/
int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
{
......@@ -121,7 +121,7 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
if( !TestMMX() )
{
fprintf( stderr, "Sorry, this program needs an MMX processor. Please run the non-MMX version.\n" );
return(0);
return( 1 );
}
#endif
p_main->p_msg = intf_MsgCreate();
......@@ -131,7 +131,7 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
strerror(errno));
return(errno);
}
if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) )/* parse command line */
if( GetConfiguration( i_argc, ppsz_argv, ppsz_env ) ) /* parse cmd line */
{
intf_MsgDestroy();
return(errno);
......@@ -432,6 +432,8 @@ static void Usage( void )
/* Video parameters */
intf_Msg("Video parameters:\n" \
" " VOUT_METHOD_VAR "=<method name> \tmethod used\n" \
" ( available: " VIDEO_OPTIONS " )\n" \
" " VOUT_DISPLAY_VAR "=<display name> \tdisplay used\n" \
" " VOUT_WIDTH_VAR "=<width> \tdisplay width\n" \
" " VOUT_HEIGHT_VAR "=<height> \tdislay height\n" \
......@@ -513,7 +515,7 @@ static void SignalHandler( int i_signal )
*****************************************************************************/
static int TestMMX( void )
{
int reg, dummy;
int i_reg, i_dummy = 0;
/* test for a 386 cpu */
asm volatile ( "pushfl
......@@ -526,9 +528,9 @@ static int TestMMX( void )
popl %%eax
xorl %%ecx, %%eax
andl $0x40000, %%eax"
: "=a" ( reg ) );
: "=a" ( i_reg ) );
if( !reg )
if( !i_reg )
return( 0 );
/* test for a 486 cpu */
......@@ -542,33 +544,35 @@ static int TestMMX( void )
pushl %%ecx
popfl
andl $0x200000, %%eax"
: "=a" ( reg ) );
: "=a" ( i_reg ) );
if( !reg )
if( !i_reg )
return( 0 );
/* the cpu supports the CPUID instruction - get its level */
asm volatile ( "cpuid"
: "=a" ( reg ),
"=b" ( dummy ),
"=c" ( dummy ),
"=d" ( dummy )
: "a" ( 0 ) ); /* level 0 */
: "=a" ( i_reg ),
"=b" ( i_dummy ),
"=c" ( i_dummy ),
"=d" ( i_dummy )
: "a" ( 0 ), /* level 0 */
"b" ( i_dummy ) ); /* buggy compiler shouldn't complain */
/* this shouldn't happen on a normal cpu */
if( !reg )
if( !i_reg )
return( 0 );
/* test for the MMX flag */
asm volatile ( "cpuid
andl $0x00800000, %%edx" /* X86_FEATURE_MMX */
: "=a" ( dummy ),
"=b" ( dummy ),
"=c" ( dummy ),
"=d" ( reg )
: "a" ( 1 ) ); /* level 1 */
if( !reg )
: "=a" ( i_dummy ),
"=b" ( i_dummy ),
"=c" ( i_dummy ),
"=d" ( i_reg )
: "a" ( 1 ), /* level 1 */
"b" ( i_dummy ) ); /* buggy compiler shouldn't complain */
if( !i_reg )
return( 0 );
return( 1 );
......
/*****************************************************************************
* vout_3dfx.c: 3dfx video output display method for 3dfx cards
* (c)2000 VideoLAN
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifndef __linux__
#include <conio.h> /* for glide ? */
#endif
#include <sys/uio.h> /* for input.h */
#include <glide.h>
#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"
#include "main.h"
#define WIDTH 640
#define HEIGHT 480
#define BITS_PER_PLANE 16
#define BYTES_PER_PIXEL 2
/*****************************************************************************
* vout_sys_t: 3dfx video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the 3dfx specific properties of an output thread.
*****************************************************************************/
typedef struct vout_sys_s
{
GrLfbInfo_t p_buffer_info; /* back buffer info */
/* Dummy video memory */
byte_t * p_video; /* base adress */
size_t i_page_size; /* page size */
} vout_sys_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int GlideOpenDisplay ( vout_thread_t *p_vout );
static void GlideCloseDisplay ( vout_thread_t *p_vout );
/*****************************************************************************
* vout_SysCreate: allocates 3dfx video thread output method
*****************************************************************************
* This function allocates and initializes a 3dfx vout method.
*****************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window )
{
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
return( 1 );
}
/* Open and initialize device */
if( GlideOpenDisplay( p_vout ) )
{
intf_ErrMsg("vout error: can't open display\n");
free( p_vout->p_sys );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* vout_SysInit: initialize 3dfx video thread output method
*****************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
return( 0 );
}
/*****************************************************************************
* vout_SysEnd: terminate 3dfx video thread output method
*****************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout )
{
;
}
/*****************************************************************************
* vout_SysDestroy: destroy 3dfx video thread output method
*****************************************************************************
* Terminate an output method created by vout_CreateOutputMethod
*****************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
GlideCloseDisplay( p_vout );
free( p_vout->p_sys );
}
/*****************************************************************************
* vout_SysManage: handle 3dfx events
*****************************************************************************
* This function should be called regularly by video output thread. It manages
* console events. It returns a non null value on error.
*****************************************************************************/
int vout_SysManage( vout_thread_t *p_vout )
{
return 0;
}
/*****************************************************************************
* vout_SysDisplay: displays previously rendered output
*****************************************************************************
* This function send the currently rendered image to 3dfx image, waits until
* it is displayed and switch the two rendering buffers, preparing next frame.
*****************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
grBufferSwap( 0 );
if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
&p_vout->p_sys->p_buffer_info) == FXFALSE )
{
intf_ErrMsg( "vout error: can't take 3dfx back buffer lock\n" );
}
}
/* following functions are local */
/*****************************************************************************
* GlideOpenDisplay: open and initialize 3dfx device
*****************************************************************************/
static int GlideOpenDisplay( vout_thread_t *p_vout )
{
static char version[80];
GrHwConfiguration hwconfig;
GrScreenResolution_t resolution = GR_RESOLUTION_640x480;
GrLfbInfo_t p_front_buffer_info; /* front buffer info */
p_vout->i_width = WIDTH;
p_vout->i_height = HEIGHT;
p_vout->i_screen_depth = BITS_PER_PLANE;
p_vout->i_bytes_per_pixel = BYTES_PER_PIXEL;
p_vout->i_bytes_per_line = 1024 * BYTES_PER_PIXEL;
p_vout->p_sys->i_page_size = WIDTH * HEIGHT * BYTES_PER_PIXEL;
p_vout->i_red_mask = 0xf800;
p_vout->i_green_mask = 0x07e0;
p_vout->i_blue_mask = 0x001f;
/* Map two framebuffers a the very beginning of the fb */
p_vout->p_sys->p_video = malloc( p_vout->p_sys->i_page_size * 2 );
if( (int)p_vout->p_sys->p_video == -1 )
{
intf_ErrMsg( "vout error: can't map video memory (%s)\n", strerror(errno) );
return( 1 );
}
grGlideGetVersion( version );
grGlideInit();
if( !grSstQueryHardware(&hwconfig) )
{
intf_ErrMsg( "vout error: can't get 3dfx hardware config\n" );
return( 1 );
}
grSstSelect( 0 );
if( !grSstWinOpen(0, resolution, GR_REFRESH_60Hz,
GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1) )
{
intf_ErrMsg( "vout error: can't open 3dfx screen\n" );
return( 1 );
}
/* disable dithering */
//grDitherMode( GR_DITHER_DISABLE );
/* clear both buffers */
grRenderBuffer( GR_BUFFER_BACKBUFFER );
grBufferClear( 0, 0, 0 );
grRenderBuffer( GR_BUFFER_FRONTBUFFER );
grBufferClear( 0, 0, 0 );
grRenderBuffer( GR_BUFFER_BACKBUFFER );
p_vout->p_sys->p_buffer_info.size = sizeof( GrLfbInfo_t );
p_front_buffer_info.size = sizeof( GrLfbInfo_t );
/* lock the buffers to find their adresses */
if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER,
GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
&p_front_buffer_info) == FXFALSE )
{
intf_ErrMsg( "vout error: can't take 3dfx front buffer lock\n" );
grGlideShutdown();
return( 1 );
}
grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_FRONTBUFFER );
if ( grLfbLock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER,
GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE,
&p_vout->p_sys->p_buffer_info) == FXFALSE )
{
intf_ErrMsg( "vout error: can't take 3dfx back buffer lock\n" );
grGlideShutdown();
return( 1 );
}
grBufferClear( 0, 0, 0 );
/* Set and initialize buffers */
vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer_info.lfbPtr,
p_front_buffer_info.lfbPtr );
return( 0 );
}
/*****************************************************************************
* GlideCloseDisplay: close and reset 3dfx device
*****************************************************************************
* Returns all resources allocated by GlideOpenDisplay and restore the original
* state of the device.
*****************************************************************************/
static void GlideCloseDisplay( vout_thread_t *p_vout )
{
/* unlock the hidden buffer */
grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
/* shutdown Glide */
grGlideShutdown();
free( p_vout->p_sys->p_video );
}
/*****************************************************************************
* vout_dummy.c: Dummy video output display method for testing purposes
* (c)2000 VideoLAN
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/uio.h> /* for input.h */
#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"
#include "main.h"
#define WIDTH 128
#define HEIGHT 64
#define BITS_PER_PLANE 16
#define BYTES_PER_PIXEL 2
/*****************************************************************************
* vout_sys_t: dummy video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the dummy specific properties of an output thread.
*****************************************************************************/
typedef struct vout_sys_s
{
/* Dummy video memory */
byte_t * p_video; /* base adress */
size_t i_page_size; /* page size */
} vout_sys_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int DummyOpenDisplay ( vout_thread_t *p_vout );
static void DummyCloseDisplay ( vout_thread_t *p_vout );
/*****************************************************************************
* vout_SysCreate: allocates dummy video thread output method
*****************************************************************************
* This function allocates and initializes a dummy vout method.
*****************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window )
{
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
return( 1 );
}
/* Open and initialize device */
if( DummyOpenDisplay( p_vout ) )
{
intf_ErrMsg("vout error: can't open display\n");
free( p_vout->p_sys );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* vout_SysInit: initialize dummy video thread output method
*****************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
return( 0 );
}
/*****************************************************************************
* vout_SysEnd: terminate dummy video thread output method
*****************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout )
{
;
}
/*****************************************************************************
* vout_SysDestroy: destroy dummy video thread output method
*****************************************************************************
* Terminate an output method created by vout_DummyCreateOutputMethod
*****************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
DummyCloseDisplay( p_vout );
free( p_vout->p_sys );
}
/*****************************************************************************
* vout_SysManage: handle dummy events
*****************************************************************************
* This function should be called regularly by video output thread. It manages
* console events. It returns a non null value on error.
*****************************************************************************/
int vout_SysManage( vout_thread_t *p_vout )
{
return 0;
}
/*****************************************************************************
* vout_SysDisplay: displays previously rendered output
*****************************************************************************
* This function send the currently rendered image to dummy image, waits until
* it is displayed and switch the two rendering buffers, preparing next frame.
*****************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
;
}
/* following functions are local */
/*****************************************************************************
* DummyOpenDisplay: open and initialize dummy device
*****************************************************************************
* ?? 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
* own risk !
*****************************************************************************/
static int DummyOpenDisplay( vout_thread_t *p_vout )
{
p_vout->i_width = WIDTH;
p_vout->i_height = HEIGHT;
p_vout->i_screen_depth = BITS_PER_PLANE;
p_vout->i_bytes_per_pixel = BYTES_PER_PIXEL;
p_vout->i_bytes_per_line = WIDTH * BYTES_PER_PIXEL;
p_vout->p_sys->i_page_size = WIDTH * HEIGHT * BYTES_PER_PIXEL;
/* Map two framebuffers a the very beginning of the fb */
p_vout->p_sys->p_video = malloc( p_vout->p_sys->i_page_size * 2 );
if( (int)p_vout->p_sys->p_video == -1 )
{
intf_ErrMsg("vout error: can't map video memory (%s)\n", strerror(errno) );
return( 1 );
}
/* Set and initialize buffers */
vout_SetBuffers( p_vout, p_vout->p_sys->p_video,
p_vout->p_sys->p_video + p_vout->p_sys->i_page_size );
return( 0 );
}
/*****************************************************************************
* DummyCloseDisplay: close and reset dummy device
*****************************************************************************
* Returns all resources allocated by DummyOpenDisplay and restore the original
* state of the device.
*****************************************************************************/
static void DummyCloseDisplay( vout_thread_t *p_vout )
{
free( p_vout->p_sys->p_video );
}
/*****************************************************************************
* vout_fb.c: Linux framebuffer video output display method
* (c)1999 VideoLAN
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/uio.h> /* for input.h */
#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"
#include "main.h"
/*****************************************************************************
* vout_sys_t: video output framebuffer method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the FB specific properties of an output thread.
*****************************************************************************/
typedef struct vout_sys_s
{
/* System informations */
int i_fb_dev; /* framebuffer device handle */
struct fb_var_screeninfo var_info; /* framebuffer mode informations */
/* Video memory */
byte_t * p_video; /* base adress */
size_t i_page_size; /* page size */
struct fb_cmap fb_cmap; /* original colormap */
unsigned short *fb_palette; /* original palette */
} vout_sys_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int FBOpenDisplay ( vout_thread_t *p_vout );
static void FBCloseDisplay ( vout_thread_t *p_vout );
static void FBSetPalette ( p_vout_thread_t p_vout,
u16 *red, u16 *green, u16 *blue, u16 *transp );
/*****************************************************************************
* 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 )
{
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
return( 1 );
}
/* Open and initialize device */
if( FBOpenDisplay( p_vout ) )
{
intf_ErrMsg("vout error: can't open display\n");
free( p_vout->p_sys );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* vout_SysInit: initialize framebuffer video thread output method
*****************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
p_vout->p_set_palette = FBSetPalette;
return( 0 );
}
/*****************************************************************************
* vout_SysEnd: terminate FB video thread output method
*****************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout )
{
;
}
/*****************************************************************************
* vout_SysDestroy: destroy FB video thread output method
*****************************************************************************
* Terminate an output method created by vout_CreateOutputMethod
*****************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
FBCloseDisplay( p_vout );
free( p_vout->p_sys );
}
/*****************************************************************************
* vout_SysManage: 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.
*****************************************************************************/
int vout_SysManage( vout_thread_t *p_vout )
{
return 0;
}
/*****************************************************************************
* vout_SysDisplay: 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.
*****************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
/* swap the two Y offsets */
p_vout->p_sys->var_info.yoffset = p_vout->i_buffer_index ? p_vout->p_sys->var_info.yres : 0;
/* 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;
//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 );
}
/* following functions are local */
/*****************************************************************************
* FBOpenDisplay: open and initialize framebuffer device
*****************************************************************************
* ?? 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
* own risk !
*****************************************************************************/
static int FBOpenDisplay( vout_thread_t *p_vout )
{
char *psz_device; /* framebuffer device path */
struct fb_fix_screeninfo fix_info; /* framebuffer fix information */
/* framebuffer palette information */
/* Open framebuffer device */
psz_device = main_GetPszVariable( VOUT_FB_DEV_VAR, VOUT_FB_DEV_DEFAULT );
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) );
return( 1 );
}
// ?? here would be the code used to save the current mode and
// ?? change to the most appropriate mode...
/* Get framebuffer device informations */
if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
{
intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
close( p_vout->p_sys->i_fb_dev );
return( 1 );
}
/* Framebuffer must have some basic properties to be usable */
//??
/* 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;
fprintf(stderr, "ypanstep is %i\n", fix_info.ypanstep);
//??ask sam p_vout->p_sys->mode_info.sync = FB_SYNC_VERT_HIGH_ACT;
//???
if( ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
{
intf_ErrMsg("vout error: can't set framebuffer informations (%s)\n", strerror(errno) );
close( p_vout->p_sys->i_fb_dev );
return( 1 );
}
/* Get some informations again, in the definitive configuration */
if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_FSCREENINFO, &fix_info ) ||
ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
{
intf_ErrMsg("vout error: can't get framebuffer informations (%s)\n", strerror(errno) );
// ?? restore fb config
close( p_vout->p_sys->i_fb_dev );
return( 1 );
}
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;
switch( p_vout->i_screen_depth )
{
case 8: /* 8 bpp */
p_vout->p_sys->fb_palette = malloc( 8 * 256 * sizeof(unsigned short) );
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->fb_palette;
p_vout->p_sys->fb_cmap.green = p_vout->p_sys->fb_palette + 256 * sizeof(unsigned short);
p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->fb_palette + 2 * 256 * sizeof(unsigned short);
p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->fb_palette + 3 * 256 * sizeof(unsigned short);
/* saves the colormap */
ioctl( p_vout->p_sys->i_fb_dev, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
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) */
p_vout->i_bytes_per_pixel = 2;
p_vout->i_bytes_per_line = p_vout->i_width * 2;
break;
case 24: /* 24 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 3;
p_vout->i_bytes_per_line = p_vout->i_width * 3;
break;
case 32: /* 32 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 4;
p_vout->i_bytes_per_line = p_vout->i_width * 4;
break;
default: /* unsupported screen depth */
intf_ErrMsg("vout error: screen depth %d is not supported\n",
p_vout->i_screen_depth);
return( 1 );
break;
}
switch( p_vout->i_screen_depth )
{
case 15:
case 16:
case 24:
case 32:
p_vout->i_red_mask = ( (1 << p_vout->p_sys->var_info.red.length) - 1 )
<< p_vout->p_sys->var_info.red.offset;
p_vout->i_green_mask = ( (1 << p_vout->p_sys->var_info.green.length) - 1 )
<< p_vout->p_sys->var_info.green.offset;
p_vout->i_blue_mask = ( (1 << p_vout->p_sys->var_info.blue.length) - 1 )
<< p_vout->p_sys->var_info.blue.offset;
}
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;
/* Map two framebuffers a the very beginning of the fb */
p_vout->p_sys->p_video = mmap(0, p_vout->p_sys->i_page_size * 2,
PROT_READ | PROT_WRITE, MAP_SHARED,
p_vout->p_sys->i_fb_dev, 0 );
if( (int)p_vout->p_sys->p_video == -1 ) //?? according to man, it is -1. What about NULL ?
{
intf_ErrMsg("vout error: can't map video memory (%s)\n", strerror(errno) );
// ?? restore fb config
close( p_vout->p_sys->i_fb_dev );
return( 1 );
}
/* Set and initialize buffers */
vout_SetBuffers( p_vout, p_vout->p_sys->p_video,
p_vout->p_sys->p_video + p_vout->p_sys->i_page_size );
intf_DbgMsg("framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d\n",
fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
return( 0 );
}
/*****************************************************************************
* FBCloseDisplay: close and reset framebuffer device
*****************************************************************************
* Returns all resources allocated by FBOpenDisplay and restore the original
* state of the device.
*****************************************************************************/
static void FBCloseDisplay( vout_thread_t *p_vout )
{
/* Restore palette */
if( p_vout->i_screen_depth == 8 );
{
ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &p_vout->p_sys->fb_cmap );
free( p_vout->p_sys->fb_palette );
}
/* Destroy window and close display */
close( p_vout->p_sys->i_fb_dev );
}
/*****************************************************************************
* FBSetPalette: sets an 8 bpp palette
*****************************************************************************
* This function sets the palette given as an argument. It does not return
* anything, but could later send information on which colors it was unable
* to set.
*****************************************************************************/
static void FBSetPalette ( p_vout_thread_t p_vout,
u16 *red, u16 *green, u16 *blue, u16 *transp )
{
struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );
}
/*****************************************************************************
* vout_ggi.c: GGI video output display method
* (c)1998 VideoLAN
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <ggi/ggi.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "video.h"
#include "video_output.h"
#include "video_sys.h"
#include "intf_msg.h"
/*****************************************************************************
* vout_sys_t: video output GGI method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the GGI specific properties of an output thread.
*****************************************************************************/
typedef struct vout_sys_s
{
/* GGI system informations */
ggi_visual_t p_display; /* display device */
/* Buffers informations */
ggi_directbuffer * p_buffer[2]; /* buffers */
boolean_t b_must_acquire; /* must be acquired before writing */
} vout_sys_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int GGIOpenDisplay ( vout_thread_t *p_vout, char *psz_display );
static void GGICloseDisplay ( vout_thread_t *p_vout );
/*****************************************************************************
* vout_SysCreate: allocate GGI video thread output method
*****************************************************************************
* This function allocate and initialize a GGI vout method. It uses some of the
* vout properties to choose the correct mode, and change them according to the
* mode actually used.
*****************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window )
{
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
return( 1 );
}
/* Open and initialize device */
if( GGIOpenDisplay( p_vout, psz_display ) )
{
intf_ErrMsg("error: can't initialize GGI display\n");
free( p_vout->p_sys );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* vout_SysInit: initialize GGI video thread output method
*****************************************************************************
* This function initialize the GGI display device.
*****************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
/* Acquire first buffer */
if( p_vout->p_sys->b_must_acquire )
{
ggiResourceAcquire( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource, GGI_ACTYPE_WRITE );
}
return( 0 );
}
/*****************************************************************************
* vout_SysEnd: terminate Sys video thread output method
*****************************************************************************
* Terminate an output method created by vout_SysCreateOutputMethod
*****************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout )
{
/* Release buffer */
if( p_vout->p_sys->b_must_acquire )
{
ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource );
}
}
/*****************************************************************************
* vout_SysDestroy: destroy Sys video thread output method
*****************************************************************************
* Terminate an output method created by vout_SysCreateOutputMethod
*****************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
GGICloseDisplay( p_vout );
free( p_vout->p_sys );
}
/*****************************************************************************
* vout_SysManage: handle Sys events
*****************************************************************************
* This function should be called regularly by video output thread. It returns
* a non null value if an error occured.
*****************************************************************************/
int vout_SysManage( vout_thread_t *p_vout )
{
//?? 8bpp: change palette
return( 0 );
}
/*****************************************************************************
* vout_SysDisplay: displays previously rendered output
*****************************************************************************
* This function send the currently rendered image to the display, wait until
* it is displayed and switch the two rendering buffer, preparing next frame.
*****************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
/* Change display frame */
if( p_vout->p_sys->b_must_acquire )
{
ggiResourceRelease( p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->resource );
}
ggiFlush( p_vout->p_sys->p_display ); // ??
ggiSetDisplayFrame( p_vout->p_sys->p_display,
p_vout->p_sys->p_buffer[ p_vout->i_buffer_index ]->frame );
/* Swap buffers and change write frame */
if( p_vout->p_sys->b_must_acquire )
{
ggiResourceAcquire( p_vout->p_sys->p_buffer[ (p_vout->i_buffer_index + 1) & 1]->resource,
GGI_ACTYPE_WRITE );
}
ggiSetWriteFrame( p_vout->p_sys->p_display,
p_vout->p_sys->p_buffer[ (p_vout->i_buffer_index + 1) & 1]->frame );
}
/*****************************************************************************
* vout_SysGetVisual: send visual to interface driver
*****************************************************************************
* This function is not part of the regular vout_Sys* API, but is used by GGI
* interface to get back visual display pointer once the output thread has
* been spawned. This visual is used to keep track of keyboard events.
*****************************************************************************/
ggi_visual_t vout_SysGetVisual( vout_thread_t *p_vout )
{
return( p_vout->p_sys->p_display );
}
/* following functions are local */
/*****************************************************************************
* GGIOpenDisplay: open and initialize GGI device
*****************************************************************************
* Open and initialize display according to preferences specified in the vout
* thread fields.
*****************************************************************************/
static int GGIOpenDisplay( vout_thread_t *p_vout, char *psz_display )
{
ggi_mode mode; /* mode descriptor */
ggi_color col_fg; /* foreground color */
ggi_color col_bg; /* background color */
int i_index; /* all purposes index */
/* Initialize library */
if( ggiInit() )
{
intf_ErrMsg("error: can't initialize GGI library\n");
return( 1 );
}
/* Open display */
p_vout->p_sys->p_display = ggiOpen( psz_display, NULL );
if( p_vout->p_sys->p_display == NULL )
{
intf_ErrMsg("error: can't open GGI default display\n");
ggiExit();
return( 1 );
}
/* Find most appropriate mode */
mode.frames = 2; /* 2 buffers */
mode.visible.x = p_vout->i_width; /* minimum width */
mode.visible.y = p_vout->i_height; /* minimum height */
mode.virt.x = GGI_AUTO;
mode.virt.y = GGI_AUTO;
mode.size.x = GGI_AUTO;
mode.size.y = GGI_AUTO;
mode.graphtype = GT_15BIT; /* minimum usable screen depth */
mode.dpp.x = GGI_AUTO;
mode.dpp.y = GGI_AUTO;
ggiCheckMode( p_vout->p_sys->p_display, &mode );
/* Check that returned mode has some minimum properties */
//??
/* Set mode */
if( ggiSetMode( p_vout->p_sys->p_display, &mode ) )
{
intf_ErrMsg("error: can't set GGI mode\n");
ggiClose( p_vout->p_sys->p_display );
ggiExit();
return( 1 );
}
/* Check buffers properties */
p_vout->p_sys->b_must_acquire = 0;
for( i_index = 0; i_index < 2; i_index++ )
{
/* Get buffer address */
p_vout->p_sys->p_buffer[ i_index ] =
ggiDBGetBuffer( p_vout->p_sys->p_display, i_index );
if( p_vout->p_sys->p_buffer[ i_index ] == NULL )
{
intf_ErrMsg("error: double buffering is not possible\n");
ggiClose( p_vout->p_sys->p_display );
ggiExit();
return( 1 );
}
/* Check buffer properties */
if( ! (p_vout->p_sys->p_buffer[ i_index ]->type & GGI_DB_SIMPLE_PLB) ||
(p_vout->p_sys->p_buffer[ i_index ]->page_size != 0) ||
(p_vout->p_sys->p_buffer[ i_index ]->write == NULL ) ||
(p_vout->p_sys->p_buffer[ i_index ]->noaccess != 0) ||
(p_vout->p_sys->p_buffer[ i_index ]->align != 0) )
{
intf_ErrMsg("error: incorrect video memory type\n");
ggiClose( p_vout->p_sys->p_display );
ggiExit();
return( 1 );
}
/* Check if buffer needs to be acquired before write */
if( ggiResourceMustAcquire( p_vout->p_sys->p_buffer[ i_index ]->resource ) )
{
p_vout->p_sys->b_must_acquire = 1;
}
}
#ifdef DEBUG
if( p_vout->p_sys->b_must_acquire )
{
intf_DbgMsg("buffers must be acquired\n");
}
#endif
/* Set graphic context colors */
col_fg.r = col_fg.g = col_fg.b = -1;
col_bg.r = col_bg.g = col_bg.b = 0;
if( ggiSetGCForeground(p_vout->p_sys->p_display,
ggiMapColor(p_vout->p_sys->p_display,&col_fg)) ||
ggiSetGCBackground(p_vout->p_sys->p_display,
ggiMapColor(p_vout->p_sys->p_display,&col_bg)) )
{
intf_ErrMsg("error: can't set colors\n");
ggiClose( p_vout->p_sys->p_display );
ggiExit();
return( 1 );
}
/* Set clipping for text */
if( ggiSetGCClipping(p_vout->p_sys->p_display, 0, 0,
mode.visible.x, mode.visible.y ) )
{
intf_ErrMsg("error: can't set clipping\n");
ggiClose( p_vout->p_sys->p_display );
ggiExit();
return( 1 );
}
/* Set thread information */
p_vout->i_width = mode.visible.x;
p_vout->i_height = mode.visible.y;
p_vout->i_bytes_per_line = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb.stride;
p_vout->i_screen_depth = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb->pixelformat.depth;
p_vout->i_bytes_per_pixel = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb->pixelformat.size / 8;
p_vout->i_red_mask = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb->pixelformat.red_mask;
p_vout->i_green_mask = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb->pixelformat.green_mask;
p_vout->i_blue_mask = p_vout->p_sys->p_buffer[ 0 ]->buffer.plb->pixelformat.blue_mask;
//?? palette in 8bpp
/* Set and initialize buffers */
vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer[ 0 ]->write, p_vout->p_sys->p_buffer[ 1 ]->write );
return( 0 );
}
/*****************************************************************************
* GGICloseDisplay: close and reset GGI device
*****************************************************************************
* This function returns all resources allocated by GGIOpenDisplay and restore
* the original state of the device.
*****************************************************************************/
static void GGICloseDisplay( vout_thread_t *p_vout )
{
// Restore original mode and close display
ggiClose( p_vout->p_sys->p_display );
// Exit library
ggiExit();
}
......@@ -66,7 +66,7 @@ static void SetPalette ( p_vout_thread_t p_vout, u16 *red,
* If not, it will be updated using one of the THREAD_* constants.
*****************************************************************************/
vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window,
int i_width, int i_height, int *pi_status )
int i_width, int i_height, int *pi_status, int i_method )
{
vout_thread_t * p_vout; /* thread descriptor */
int i_status; /* thread status */
......@@ -81,6 +81,83 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
return( NULL );
}
/* Sets method-specific functions */
switch( i_method )
{
case VOUT_DUMMY_METHOD:
p_vout->p_sys_create = vout_DummySysCreate;
p_vout->p_sys_init = vout_DummySysInit;
p_vout->p_sys_end = vout_DummySysEnd;
p_vout->p_sys_destroy = vout_DummySysDestroy;
p_vout->p_sys_manage = vout_DummySysManage;
p_vout->p_sys_display = vout_DummySysDisplay;
break;
#ifdef VIDEO_X11
case VOUT_X11_METHOD:
p_vout->p_sys_create = vout_X11SysCreate;
p_vout->p_sys_init = vout_X11SysInit;
p_vout->p_sys_end = vout_X11SysEnd;
p_vout->p_sys_destroy = vout_X11SysDestroy;
p_vout->p_sys_manage = vout_X11SysManage;
p_vout->p_sys_display = vout_X11SysDisplay;
break;
#endif
#ifdef VIDEO_FB
case VOUT_FB_METHOD:
p_vout->p_sys_create = vout_FBSysCreate;
p_vout->p_sys_init = vout_FBSysInit;
p_vout->p_sys_end = vout_FBSysEnd;
p_vout->p_sys_destroy = vout_FBSysDestroy;
p_vout->p_sys_manage = vout_FBSysManage;
p_vout->p_sys_display = vout_FBSysDisplay;
break;
#endif
#ifdef VIDEO_GLIDE
case VOUT_GLIDE_METHOD:
p_vout->p_sys_create = vout_GlideSysCreate;
p_vout->p_sys_init = vout_GlideSysInit;
p_vout->p_sys_end = vout_GlideSysEnd;
p_vout->p_sys_destroy = vout_GlideSysDestroy;
p_vout->p_sys_manage = vout_GlideSysManage;
p_vout->p_sys_display = vout_GlideSysDisplay;
break;
#endif
#ifdef VIDEO_DGA
case VOUT_DGA_METHOD:
p_vout->p_sys_create = vout_DGASysCreate;
p_vout->p_sys_init = vout_DGASysInit;
p_vout->p_sys_end = vout_DGASysEnd;
p_vout->p_sys_destroy = vout_DGASysDestroy;
p_vout->p_sys_manage = vout_DGASysManage;
p_vout->p_sys_display = vout_DGASysDisplay;
break;
#endif
#ifdef VIDEO_GGI
case VOUT_GGI_METHOD:
p_vout->p_sys_create = vout_GGISysCreate;
p_vout->p_sys_init = vout_GGISysInit;
p_vout->p_sys_end = vout_GGISysEnd;
p_vout->p_sys_destroy = vout_GGISysDestroy;
p_vout->p_sys_manage = vout_GGISysManage;
p_vout->p_sys_display = vout_GGISysDisplay;
break;
#endif
#ifdef VIDEO_BEOS
case VOUT_BEOS_METHOD:
p_vout->p_sys_create = vout_BeSysCreate;
p_vout->p_sys_init = vout_BeSysInit;
p_vout->p_sys_end = vout_BeSysEnd;
p_vout->p_sys_destroy = vout_BeSysDestroy;
p_vout->p_sys_manage = vout_BeSysManage;
p_vout->p_sys_display = vout_BeSysDisplay;
break;
#endif
default:
intf_ErrMsg( "error: video output method not available\n" );
free( p_vout );
return( NULL );
}
/* Initialize thread properties - thread id and locks will be initialized
* later */
p_vout->b_die = 0;
......@@ -136,7 +213,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
/* Create and initialize system-dependant method - this function issues its
* own error messages */
if( vout_SysCreate( p_vout, psz_display, i_root_window ) )
if( p_vout->p_sys_create( p_vout, psz_display, i_root_window ) )
{
free( p_vout );
return( NULL );
......@@ -157,12 +234,12 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
p_vout->i_gray_pixel = RGB2PIXEL( p_vout, 128, 128, 128 );
p_vout->i_blue_pixel = RGB2PIXEL( p_vout, 0, 0, 50 );
/* Load fonts - fonts must be initialized after the systme method since
* they may be dependant of screen depth and other thread properties */
/* Load fonts - fonts must be initialized after the system method since
* they may be dependant on screen depth and other thread properties */
p_vout->p_default_font = vout_LoadFont( VOUT_DEFAULT_FONT );
if( p_vout->p_default_font == NULL )
{
vout_SysDestroy( p_vout );
p_vout->p_sys_destroy( p_vout );
free( p_vout );
return( NULL );
}
......@@ -170,7 +247,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
if( p_vout->p_large_font == NULL )
{
vout_UnloadFont( p_vout->p_default_font );
vout_SysDestroy( p_vout );
p_vout->p_sys_destroy( p_vout );
free( p_vout );
return( NULL );
}
......@@ -185,7 +262,7 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_
intf_ErrMsg("error: %s\n", strerror(ENOMEM));
vout_UnloadFont( p_vout->p_default_font );
vout_UnloadFont( p_vout->p_large_font );
vout_SysDestroy( p_vout );
p_vout->p_sys_destroy( p_vout );
free( p_vout );
return( NULL );
}
......@@ -825,7 +902,7 @@ static int InitThread( vout_thread_t *p_vout )
*p_vout->pi_status = THREAD_START;
/* Initialize output method - this function issues its own error messages */
if( vout_SysInit( p_vout ) )
if( p_vout->p_sys_init( p_vout ) )
{
return( 1 );
}
......@@ -1063,14 +1140,14 @@ static void RunThread( vout_thread_t *p_vout)
#endif
if( b_display && !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) )
{
vout_SysDisplay( p_vout );
p_vout->p_sys_display( p_vout );
p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1;
}
/*
* Check events and manage thread
*/
if( vout_SysManage( p_vout ) | Manage( p_vout ) )
if( p_vout->p_sys_manage( p_vout ) | Manage( p_vout ) )
{
/* A fatal error occured, and the thread must terminate immediately,
* without displaying anything - setting b_error to 1 cause the
......@@ -1140,7 +1217,7 @@ static void EndThread( vout_thread_t *p_vout )
/* Destroy translation tables */
vout_EndYUV( p_vout );
vout_SysEnd( p_vout );
p_vout->p_sys_end( p_vout );
}
/*****************************************************************************
......@@ -1160,7 +1237,7 @@ static void DestroyThread( vout_thread_t *p_vout, int i_status )
/* Destroy thread structures allocated by Create and InitThread */
vout_UnloadFont( p_vout->p_default_font );
vout_UnloadFont( p_vout->p_large_font );
vout_SysDestroy( p_vout );
p_vout->p_sys_destroy( p_vout );
free( p_vout );
*pi_status = i_status;
}
......@@ -1823,8 +1900,8 @@ static int Manage( vout_thread_t *p_vout )
/* Detect unauthorized changes */
if( p_vout->i_changes )
{
/* Some changes were not acknowledged by vout_SysManage or this function,
* it means they should not be authorized */
/* Some changes were not acknowledged by p_vout->p_sys_manage or this
* function, it means they should not be authorized */
intf_ErrMsg( "error: unauthorized changes in the video output thread\n" );
return( 1 );
}
......
/*****************************************************************************
* vout_x11.c: X11 video output display method
* (c)1998 VideoLAN
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "video.h"
#include "video_output.h"
#include "video_sys.h"
#include "video_yuv.h"
#include "intf_msg.h"
/*****************************************************************************
* vout_sys_t: video output X11 method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the X11 specific properties of an output thread. X11 video
* output is performed through regular resizable windows. Windows can be
* dynamically resized to adapt to the size of the streams.
*****************************************************************************/
typedef struct vout_sys_s
{
/* User settings */
boolean_t b_shm; /* shared memory extension flag */
/* Internal settings and properties */
Display * p_display; /* display pointer */
Visual * p_visual; /* visual pointer */
int i_screen; /* screen number */
Window root_window; /* root window */
Window window; /* window instance handler */
GC gc; /* graphic context instance handler */
Colormap colormap; /* colormap used (8bpp only) */
/* Display buffers and shared memory information */
XImage * p_ximage[2]; /* XImage pointer */
XShmSegmentInfo shm_info[2]; /* shared memory zone information */
} vout_sys_t;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int X11OpenDisplay ( vout_thread_t *p_vout, char *psz_display, Window root_window );
static void X11CloseDisplay ( vout_thread_t *p_vout );
static int X11CreateWindow ( vout_thread_t *p_vout );
static void X11DestroyWindow ( vout_thread_t *p_vout );
static int X11CreateImage ( vout_thread_t *p_vout, XImage **pp_ximage );
static void X11DestroyImage ( XImage *p_ximage );
static int X11CreateShmImage ( vout_thread_t *p_vout, XImage **pp_ximage,
XShmSegmentInfo *p_shm_info );
static void X11DestroyShmImage ( vout_thread_t *p_vout, XImage *p_ximage,
XShmSegmentInfo *p_shm_info );
/*****************************************************************************
* vout_SysCreate: allocate X11 video thread output method
*****************************************************************************
* This function allocate and initialize a X11 vout method. It uses some of the
* vout properties to choose the window size, and change them according to the
* actual properties of the display.
*****************************************************************************/
int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window )
{
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
return( 1 );
}
/* Open and initialize device. This function issues its own error messages.
* Since XLib is usually not thread-safe, we can't use the same display
* pointer than the interface or another thread. However, the root window
* id is still valid. */
if( X11OpenDisplay( p_vout, psz_display, i_root_window ) )
{
intf_ErrMsg("error: can't initialize X11 display\n" );
free( p_vout->p_sys );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* vout_SysInit: initialize X11 video thread output method
*****************************************************************************
* This function create the XImages needed by the output thread. It is called
* at the beginning of the thread, but also each time the window is resized.
*****************************************************************************/
int vout_SysInit( vout_thread_t *p_vout )
{
int i_err;
/* Create XImages using XShm extension - on failure, fall back to regular
* way (and destroy the first image if it was created successfully) */
if( p_vout->p_sys->b_shm )
{
/* Create first image */
i_err = X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[0],
&p_vout->p_sys->shm_info[0] );
if( !i_err ) /* first image has been created */
{
/* Create second image */
if( X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[1],
&p_vout->p_sys->shm_info[1] ) )
{ /* error creating the second image */
X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0],
&p_vout->p_sys->shm_info[0] );
i_err = 1;
}
}
if( i_err ) /* an error occured */
{
intf_Msg("XShm video sextension desactivated\n" );
p_vout->p_sys->b_shm = 0;
}
}
/* Create XImages without XShm extension */
if( !p_vout->p_sys->b_shm )
{
if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[0] ) )
{
intf_ErrMsg("error: can't create images\n");
p_vout->p_sys->p_ximage[0] = NULL;
p_vout->p_sys->p_ximage[1] = NULL;
return( 1 );
}
if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[1] ) )
{
intf_ErrMsg("error: can't create images\n");
X11DestroyImage( p_vout->p_sys->p_ximage[0] );
p_vout->p_sys->p_ximage[0] = NULL;
p_vout->p_sys->p_ximage[1] = NULL;
return( 1 );
}
}
/* Set bytes per line and initialize buffers */
p_vout->i_bytes_per_line = p_vout->p_sys->p_ximage[0]->bytes_per_line;
vout_SetBuffers( p_vout, p_vout->p_sys->p_ximage[ 0 ]->data,
p_vout->p_sys->p_ximage[ 1 ]->data );
return( 0 );
}
/*****************************************************************************
* vout_SysEnd: terminate X11 video thread output method
*****************************************************************************
* Destroy the X11 XImages created by vout_SysInit. It is called at the end of
* the thread, but also each time the window is resized.
*****************************************************************************/
void vout_SysEnd( vout_thread_t *p_vout )
{
if( p_vout->p_sys->b_shm ) /* Shm XImages... */
{
X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0],
&p_vout->p_sys->shm_info[0] );
X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[1],
&p_vout->p_sys->shm_info[1] );
}
else /* ...or regular XImages */
{
X11DestroyImage( p_vout->p_sys->p_ximage[0] );
X11DestroyImage( p_vout->p_sys->p_ximage[1] );
}
}
/*****************************************************************************
* vout_SysDestroy: destroy X11 video thread output method
*****************************************************************************
* Terminate an output method created by vout_X11CreateOutputMethod
*****************************************************************************/
void vout_SysDestroy( vout_thread_t *p_vout )
{
X11CloseDisplay( p_vout );
free( p_vout->p_sys );
}
/*****************************************************************************
* vout_SysManage: handle X11 events
*****************************************************************************
* This function should be called regularly by video output thread. It manages
* X11 events and allows window resizing. It returns a non null value on
* error.
*****************************************************************************/
int vout_SysManage( vout_thread_t *p_vout )
{
/*
* Color/Grayscale or gamma change: in 8bpp, just change the colormap
*/
if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE) && (p_vout->i_screen_depth == 8) )
{
//??
//?? clear flags
}
/*
* Size change
*/
if( p_vout->i_changes & VOUT_SIZE_CHANGE )
{
intf_DbgMsg("resizing window\n");
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
/* Resize window */
XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
p_vout->i_width, p_vout->i_height );
/* Destroy XImages to change their size */
vout_SysEnd( p_vout );
/* Recreate XImages. If SysInit failed, the thread can't go on. */
if( vout_SysInit( p_vout ) )
{
intf_ErrMsg("error: can't resize display\n");
return( 1 );
}
/* Tell the video output thread that it will need to rebuild YUV
* tables. This is needed since convertion buffer size may have changed */
p_vout->i_changes |= VOUT_YUV_CHANGE;
intf_Msg("Video display resized (%dx%d)\n", p_vout->i_width, p_vout->i_height);
}
return 0;
}
/*****************************************************************************
* vout_SysDisplay: displays previously rendered output
*****************************************************************************
* This function send the currently rendered image to X11 server, wait until
* it is displayed and switch the two rendering buffer, preparing next frame.
*****************************************************************************/
void vout_SysDisplay( vout_thread_t *p_vout )
{
if( p_vout->p_sys->b_shm) /* XShm is used */
{
/* Display rendered image using shared memory extension */
XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ],
0, 0, 0, 0,
p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->width,
p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->height, True);
/* Send the order to the X server */
XFlush(p_vout->p_sys->p_display);
}
else /* regular X11 capabilities are used */
{
XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc,
p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ],
0, 0, 0, 0,
p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->width,
p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->height);
/* Send the order to the X server */
XFlush(p_vout->p_sys->p_display);
}
}
/* following functions are local */
/*****************************************************************************
* X11OpenDisplay: open and initialize X11 device
*****************************************************************************
* Create a window according to video output given size, and set other
* properties according to the display properties.
*****************************************************************************/
static int X11OpenDisplay( vout_thread_t *p_vout, char *psz_display, Window root_window )
{
XPixmapFormatValues * p_xpixmap_format; /* pixmap formats */
XVisualInfo * p_xvisual; /* visuals informations */
XVisualInfo xvisual_template; /* visual template */
int i_count; /* array size */
/* Open display */
p_vout->p_sys->p_display = XOpenDisplay( psz_display );
if( p_vout->p_sys->p_display == NULL )
{
intf_ErrMsg("error: can't open display %s\n", psz_display );
return( 1 );
}
/* Initialize structure */
p_vout->p_sys->root_window = root_window;
p_vout->p_sys->b_shm = (XShmQueryExtension(p_vout->p_sys->p_display) == True);
p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
if( !p_vout->p_sys->b_shm )
{
intf_Msg("XShm video extension is not available\n");
}
/* Get screen depth */
p_vout->i_screen_depth = XDefaultDepth( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
switch( p_vout->i_screen_depth )
{
case 8:
/*
* Screen depth is 8bpp. Use PseudoColor visual with private colormap.
*/
xvisual_template.screen = p_vout->p_sys->i_screen;
xvisual_template.class = DirectColor;
p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display, VisualScreenMask | VisualClassMask,
&xvisual_template, &i_count );
if( p_xvisual == NULL )
{
intf_ErrMsg("error: no PseudoColor visual available\n");
XCloseDisplay( p_vout->p_sys->p_display );
return( 1 );
}
//??
//?? SetColormap;
p_vout->i_bytes_per_pixel = 1;
break;
case 15:
case 16:
case 24:
default:
/*
* Screen depth is higher than 8bpp. TrueColor visual is used.
*/
xvisual_template.screen = p_vout->p_sys->i_screen;
xvisual_template.class = TrueColor;
p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display, VisualScreenMask | VisualClassMask,
&xvisual_template, &i_count );
if( p_xvisual == NULL )
{
intf_ErrMsg("error: no TrueColor visual available\n");
XCloseDisplay( p_vout->p_sys->p_display );
return( 1 );
}
p_vout->i_red_mask = p_xvisual->red_mask;
p_vout->i_green_mask = p_xvisual->green_mask;
p_vout->i_blue_mask = p_xvisual->blue_mask;
/* There is no difference yet between 3 and 4 Bpp. The only way to find
* the actual number of bytes per pixel is to list supported pixmap
* formats. */
p_xpixmap_format = XListPixmapFormats( p_vout->p_sys->p_display, &i_count );
p_vout->i_bytes_per_pixel = 0;
for( ; i_count--; p_xpixmap_format++ )
{
if( p_xpixmap_format->bits_per_pixel / 8 > p_vout->i_bytes_per_pixel )
{
p_vout->i_bytes_per_pixel = p_xpixmap_format->bits_per_pixel / 8;
}
}
break;
}
p_vout->p_sys->p_visual = p_xvisual->visual;
XFree( p_xvisual );
/* Create a window */
if( X11CreateWindow( p_vout ) )
{
intf_ErrMsg("error: can't open a window\n");
XCloseDisplay( p_vout->p_sys->p_display );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* X11CloseDisplay: close X11 device
*****************************************************************************
* Returns all resources allocated by X11OpenDisplay and restore the original
* state of the display.
*****************************************************************************/
static void X11CloseDisplay( vout_thread_t *p_vout )
{
/* Destroy colormap */
if( p_vout->i_screen_depth == 8 )
{
XFreeColormap( p_vout->p_sys->p_display, p_vout->p_sys->colormap );
}
/* Destroy window and close display */
X11DestroyWindow( p_vout );
XCloseDisplay( p_vout->p_sys->p_display );
}
/*****************************************************************************
* X11CreateWindow: create X11 vout window
*****************************************************************************
* The video output window will be created. Normally, this window is wether
* full screen or part of a parent window. Therefore, it does not need a
* title or other hints. Thery are still supplied in case the window would be
* spawned as a standalone one by the interface.
*****************************************************************************/
static int X11CreateWindow( vout_thread_t *p_vout )
{
XSetWindowAttributes xwindow_attributes; /* window attributes */
XGCValues xgcvalues; /* graphic context configuration */
XEvent xevent; /* first events */
boolean_t b_expose; /* 'expose' event received */
boolean_t b_map_notify; /* 'map_notify' event received */
/* Prepare window attributes */
xwindow_attributes.backing_store = Always; /* save the hidden part */
/* Create the window and set hints */
p_vout->p_sys->window = XCreateSimpleWindow( p_vout->p_sys->p_display,
p_vout->p_sys->root_window,
0, 0,
p_vout->i_width, p_vout->i_height,
0, 0, 0);
XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
ExposureMask | StructureNotifyMask );
XChangeWindowAttributes( p_vout->p_sys->p_display, p_vout->p_sys->window,
CWBackingStore, &xwindow_attributes);
/* Creation of a graphic context that doesn't generate a GraphicsExpose event
when using functions like XCopyArea */
xgcvalues.graphics_exposures = False;
p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display, p_vout->p_sys->window,
GCGraphicsExposures, &xgcvalues);
/* Send orders to server, and wait until window is displayed - two events
* must be received: a MapNotify event, an Expose event allowing drawing in the
* window */
b_expose = 0;
b_map_notify = 0;
XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
do
{
XNextEvent( p_vout->p_sys->p_display, &xevent);
if( (xevent.type == Expose)
&& (xevent.xexpose.window == p_vout->p_sys->window) )
{
b_expose = 1;
}
else if( (xevent.type == MapNotify)
&& (xevent.xmap.window == p_vout->p_sys->window) )
{
b_map_notify = 1;
}
}
while( !( b_expose && b_map_notify ) );
XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window, 0 );
/* At this stage, the window is openned, displayed, and ready to receive
* data */
return( 0 );
}
/*****************************************************************************
* X11DestroyWindow: destroy X11 window
*****************************************************************************
* Destroy an X11 window created by vout_X11CreateWindow
*****************************************************************************/
static void X11DestroyWindow( vout_thread_t *p_vout )
{
XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
}
/*****************************************************************************
* X11CreateImage: create an XImage
*****************************************************************************
* Create a simple XImage used as a buffer.
*****************************************************************************/
static int X11CreateImage( vout_thread_t *p_vout, XImage **pp_ximage )
{
byte_t * pb_data; /* image data storage zone */
int i_quantum; /* XImage quantum (see below) */
/* Allocate memory for image */
p_vout->i_bytes_per_line = p_vout->i_width * p_vout->i_bytes_per_pixel;
pb_data = (byte_t *) malloc( p_vout->i_bytes_per_line * p_vout->i_height );
if( !pb_data ) /* error */
{
intf_ErrMsg("error: %s\n", strerror(ENOMEM));
return( 1 );
}
/* Optimize the quantum of a scanline regarding its size - the quantum is
a diviser of the number of bits between the start of two scanlines. */
if( !(( p_vout->i_bytes_per_line ) % 32) )
{
i_quantum = 32;
}
else
{
if( !(( p_vout->i_bytes_per_line ) % 16) )
{
i_quantum = 16;
}
else
{
i_quantum = 8;
}
}
/* Create XImage */
*pp_ximage = XCreateImage( p_vout->p_sys->p_display, p_vout->p_sys->p_visual,
p_vout->i_screen_depth, ZPixmap, 0, pb_data,
p_vout->i_width, p_vout->i_height, i_quantum, 0);
if(! *pp_ximage ) /* error */
{
intf_ErrMsg( "error: XCreateImage() failed\n" );
free( pb_data );
return( 1 );
}
return 0;
}
/*****************************************************************************
* X11CreateShmImage: create an XImage using shared memory extension
*****************************************************************************
* Prepare an XImage for DisplayX11ShmImage function.
* The order of the operations respects the recommandations of the mit-shm
* document by J.Corbet and K.Packard. Most of the parameters were copied from
* there.
*****************************************************************************/
static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
XShmSegmentInfo *p_shm_info)
{
/* Create XImage */
*pp_ximage = XShmCreateImage( p_vout->p_sys->p_display, p_vout->p_sys->p_visual,
p_vout->i_screen_depth, ZPixmap, 0,
p_shm_info, p_vout->i_width, p_vout->i_height );
if(! *pp_ximage ) /* error */
{
intf_ErrMsg("error: XShmCreateImage() failed\n");
return( 1 );
}
/* Allocate shared memory segment - 0777 set the access permission
* rights (like umask), they are not yet supported by X servers */
p_shm_info->shmid = shmget( IPC_PRIVATE,
(*pp_ximage)->bytes_per_line * (*pp_ximage)->height,
IPC_CREAT | 0777);
if( p_shm_info->shmid < 0) /* error */
{
intf_ErrMsg("error: can't allocate shared image data (%s)\n",
strerror(errno));
XDestroyImage( *pp_ximage );
return( 1 );
}
/* Attach shared memory segment to process (read/write) */
p_shm_info->shmaddr = (*pp_ximage)->data = shmat(p_shm_info->shmid, 0, 0);
if(! p_shm_info->shmaddr )
{ /* error */
intf_ErrMsg("error: can't attach shared memory (%s)\n",
strerror(errno));
shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* free shared memory */
XDestroyImage( *pp_ximage );
return( 1 );
}
/* Mark the shm segment to be removed when there will be no more
* attachements, so it is automatic on process exit or after shmdt */
shmctl( p_shm_info->shmid, IPC_RMID, 0 );
/* Attach shared memory segment to X server (read only) */
p_shm_info->readOnly = True;
if( XShmAttach( p_vout->p_sys->p_display, p_shm_info ) == False ) /* error */
{
intf_ErrMsg("error: can't attach shared memory to X11 server\n");
shmdt( p_shm_info->shmaddr ); /* detach shared memory from process
* and automatic free */
XDestroyImage( *pp_ximage );
return( 1 );
}
/* Send image to X server. This instruction is required, since having
* built a Shm XImage and not using it causes an error on XCloseDisplay */
XFlush( p_vout->p_sys->p_display );
return( 0 );
}
/*****************************************************************************
* X11DestroyImage: destroy an XImage
*****************************************************************************
* Destroy XImage AND associated data. If pointer is NULL, the image won't be
* destroyed (see vout_X11ManageOutputMethod())
*****************************************************************************/
static void X11DestroyImage( XImage *p_ximage )
{
if( p_ximage != NULL )
{
XDestroyImage( p_ximage ); /* no free() required */
}
}
/*****************************************************************************
* X11DestroyShmImage
*****************************************************************************
* Destroy XImage AND associated data. Detach shared memory segment from
* server and process, then free it. If pointer is NULL, the image won't be
* destroyed (see vout_X11ManageOutputMethod())
*****************************************************************************/
static void X11DestroyShmImage( vout_thread_t *p_vout, XImage *p_ximage,
XShmSegmentInfo *p_shm_info )
{
/* If pointer is NULL, do nothing */
if( p_ximage == NULL )
{
return;
}
XShmDetach( p_vout->p_sys->p_display, p_shm_info ); /* detach from server */
XDestroyImage( p_ximage );
if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
{ /* also automatic freeing... */
intf_ErrMsg("error: can't detach shared memory (%s)\n",
strerror(errno));
}
}
......@@ -360,7 +360,7 @@ void vpar_SynchroEnd( vpar_thread_t * p_vpar )
i_decode_time = (mdate() -
p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_start].i_decode_date)
/ (p_vpar->synchro.i_fifo_stop - p_vpar->synchro.i_fifo_start & 0x0f);
/ ( (p_vpar->synchro.i_fifo_stop - p_vpar->synchro.i_fifo_start) & 0x0f);
p_vpar->synchro.i_mean_decode_time =
( 7 * p_vpar->synchro.i_mean_decode_time + i_decode_time ) / 8;
......@@ -380,9 +380,9 @@ mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar )
{
mtime_t i_displaydate = p_vpar->synchro.i_last_display_pts;
static mtime_t i_delta = 0;
#if 0
static mtime_t i_delta = 0;
fprintf( stderr,
"displaying type %i with delay %lli and delta %lli\n",
p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_start].i_image_type,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment