2012-04-21 21:13:50 +00:00
/* RetroArch - A frontend for libretro.
2012-01-08 00:08:18 +00:00
* Copyright ( C ) 2010 - 2012 - Hans - Kristian Arntzen
2010-12-24 00:33:40 +00:00
*
2012-04-21 21:13:50 +00:00
* RetroArch is free software : you can redistribute it and / or modify it under the terms
2010-12-24 00:33:40 +00:00
* of the GNU General Public License as published by the Free Software Found -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
2012-04-21 21:13:50 +00:00
* RetroArch is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
2010-12-24 00:33:40 +00:00
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
2012-04-21 21:31:57 +00:00
* You should have received a copy of the GNU General Public License along with RetroArch .
2010-12-24 00:33:40 +00:00
* If not , see < http : //www.gnu.org/licenses/>.
*/
2010-12-24 00:26:36 +00:00
# include "driver.h"
# include "general.h"
2011-03-29 16:04:41 +00:00
# include "file.h"
2010-12-24 00:26:36 +00:00
# include <stdio.h>
2010-12-29 18:43:17 +00:00
# include <string.h>
2011-03-07 18:12:14 +00:00
# include <math.h>
2012-03-16 22:26:57 +00:00
# include "compat/posix_string.h"
2011-01-07 16:59:53 +00:00
# ifdef HAVE_CONFIG_H
2010-12-30 02:02:30 +00:00
# include "config.h"
2011-01-07 16:59:53 +00:00
# endif
2010-12-24 00:26:36 +00:00
2010-12-29 19:50:50 +00:00
static const audio_driver_t * audio_drivers [ ] = {
2010-12-29 19:05:57 +00:00
# ifdef HAVE_ALSA
& audio_alsa ,
# endif
2011-06-16 21:20:12 +00:00
# if defined(HAVE_OSS) || defined(HAVE_OSS_BSD)
2010-12-29 19:05:57 +00:00
& audio_oss ,
# endif
# ifdef HAVE_RSOUND
& audio_rsound ,
# endif
2011-08-08 15:27:52 +00:00
# ifdef HAVE_COREAUDIO
& audio_coreaudio ,
# endif
2010-12-29 19:05:57 +00:00
# ifdef HAVE_AL
& audio_openal ,
# endif
# ifdef HAVE_ROAR
& audio_roar ,
# endif
2011-01-01 02:53:30 +00:00
# ifdef HAVE_JACK
& audio_jack ,
# endif
2011-01-07 14:50:16 +00:00
# ifdef HAVE_SDL
& audio_sdl ,
# endif
2011-01-27 00:46:00 +00:00
# ifdef HAVE_XAUDIO
& audio_xa ,
# endif
2011-08-04 16:45:40 +00:00
# ifdef HAVE_DSOUND
& audio_dsound ,
# endif
2011-01-29 00:15:09 +00:00
# ifdef HAVE_PULSE
& audio_pulse ,
# endif
2011-05-14 23:46:11 +00:00
# ifdef HAVE_DYLIB
& audio_ext ,
# endif
2011-12-14 11:49:13 +00:00
# ifdef __CELLOS_LV2__
& audio_ps3 ,
# endif
2011-12-13 22:17:37 +00:00
# ifdef XENON
& audio_xenon360 ,
# endif
2012-06-24 21:31:36 +00:00
# ifdef _XBOX360
2012-01-05 12:30:13 +00:00
& audio_xdk360 ,
# endif
2011-12-14 11:49:13 +00:00
# ifdef GEKKO
& audio_wii ,
# endif
2012-06-19 22:43:41 +00:00
& audio_null ,
2010-12-29 19:05:57 +00:00
} ;
2010-12-29 19:50:50 +00:00
static const video_driver_t * video_drivers [ ] = {
2011-11-01 17:24:43 +00:00
# ifdef HAVE_OPENGL
2010-12-29 19:05:57 +00:00
& video_gl ,
2011-11-01 17:24:43 +00:00
# endif
2011-12-15 12:54:22 +00:00
# ifdef XENON
& video_xenon360 ,
# endif
2012-07-07 17:15:06 +00:00
# ifdef _XBOX
& video_xdk_d3d ,
2012-01-05 12:30:13 +00:00
# endif
2011-11-01 17:24:43 +00:00
# ifdef HAVE_SDL
2011-04-21 01:23:44 +00:00
& video_sdl ,
2010-12-29 19:05:57 +00:00
# endif
2011-03-13 03:51:09 +00:00
# ifdef HAVE_XVIDEO
& video_xvideo ,
# endif
2011-05-11 15:57:31 +00:00
# ifdef HAVE_DYLIB
& video_ext ,
# endif
2011-12-14 20:44:03 +00:00
# ifdef GEKKO
& video_wii ,
# endif
2012-05-23 06:31:29 +00:00
# ifdef HAVE_RPI
& video_rpi ,
# endif
2012-06-19 22:43:41 +00:00
& video_null ,
2010-12-29 19:05:57 +00:00
} ;
2011-01-06 17:34:11 +00:00
static const input_driver_t * input_drivers [ ] = {
2011-12-02 01:41:32 +00:00
# ifdef __CELLOS_LV2__
2011-12-02 01:22:29 +00:00
& input_ps3 ,
# endif
2011-01-06 17:34:11 +00:00
# ifdef HAVE_SDL
& input_sdl ,
# endif
2011-05-11 15:57:31 +00:00
# ifdef HAVE_XVIDEO
& input_x ,
# endif
2011-12-14 00:35:17 +00:00
# ifdef XENON
& input_xenon360 ,
# endif
2012-07-07 17:56:46 +00:00
# if defined(HAVE_XINPUT2) || defined(HAVE_XINPUT_XBOX1)
& input_xinput ,
2012-01-05 12:30:13 +00:00
# endif
2011-12-14 20:44:03 +00:00
# ifdef GEKKO
& input_wii ,
# endif
2012-05-25 19:44:39 +00:00
# ifdef IS_LINUX
& input_linuxraw ,
# endif
2012-06-19 22:43:41 +00:00
& input_null ,
2011-01-06 17:34:11 +00:00
} ;
2010-12-29 19:50:50 +00:00
static void find_audio_driver ( void )
{
2011-10-30 00:12:00 +00:00
for ( unsigned i = 0 ; i < sizeof ( audio_drivers ) / sizeof ( audio_driver_t * ) ; i + + )
2010-12-29 19:50:50 +00:00
{
if ( strcasecmp ( g_settings . audio . driver , audio_drivers [ i ] - > ident ) = = 0 )
{
driver . audio = audio_drivers [ i ] ;
return ;
}
}
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Couldn't find any audio driver named \" %s \" \n " , g_settings . audio . driver ) ;
2010-12-29 19:56:56 +00:00
fprintf ( stderr , " Available audio drivers are: \n " ) ;
2011-12-24 12:46:12 +00:00
for ( size_t i = 0 ; i < sizeof ( audio_drivers ) / sizeof ( audio_driver_t * ) ; i + + )
2010-12-29 19:56:56 +00:00
fprintf ( stderr , " \t %s \n " , audio_drivers [ i ] - > ident ) ;
2012-04-21 21:25:32 +00:00
rarch_fail ( 1 , " find_audio_driver() " ) ;
2010-12-29 19:50:50 +00:00
}
static void find_video_driver ( void )
{
2011-10-30 00:12:00 +00:00
for ( unsigned i = 0 ; i < sizeof ( video_drivers ) / sizeof ( video_driver_t * ) ; i + + )
2010-12-29 19:50:50 +00:00
{
if ( strcasecmp ( g_settings . video . driver , video_drivers [ i ] - > ident ) = = 0 )
{
driver . video = video_drivers [ i ] ;
return ;
}
}
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Couldn't find any video driver named \" %s \" \n " , g_settings . video . driver ) ;
2010-12-29 19:56:56 +00:00
fprintf ( stderr , " Available video drivers are: \n " ) ;
2011-12-24 12:46:12 +00:00
for ( size_t i = 0 ; i < sizeof ( video_drivers ) / sizeof ( video_driver_t * ) ; i + + )
2010-12-29 19:56:56 +00:00
fprintf ( stderr , " \t %s \n " , video_drivers [ i ] - > ident ) ;
2012-04-21 21:25:32 +00:00
rarch_fail ( 1 , " find_video_driver() " ) ;
2010-12-29 19:50:50 +00:00
}
2010-12-29 19:05:57 +00:00
2011-01-06 17:34:11 +00:00
static void find_input_driver ( void )
{
2011-10-30 00:12:00 +00:00
for ( unsigned i = 0 ; i < sizeof ( input_drivers ) / sizeof ( input_driver_t * ) ; i + + )
2011-01-06 17:34:11 +00:00
{
if ( strcasecmp ( g_settings . input . driver , input_drivers [ i ] - > ident ) = = 0 )
{
driver . input = input_drivers [ i ] ;
return ;
}
}
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Couldn't find any input driver named \" %s \" \n " , g_settings . input . driver ) ;
2011-01-06 19:01:32 +00:00
fprintf ( stderr , " Available input drivers are: \n " ) ;
2011-12-24 12:46:12 +00:00
for ( size_t i = 0 ; i < sizeof ( input_drivers ) / sizeof ( input_driver_t * ) ; i + + )
2011-06-10 14:55:05 +00:00
fprintf ( stderr , " \t %s \n " , input_drivers [ i ] - > ident ) ;
2011-01-06 17:34:11 +00:00
2012-04-21 21:25:32 +00:00
rarch_fail ( 1 , " find_input_driver() " ) ;
2011-01-06 17:34:11 +00:00
}
2012-04-01 17:38:50 +00:00
void init_drivers_pre ( void )
{
find_audio_driver ( ) ;
find_video_driver ( ) ;
find_input_driver ( ) ;
}
2010-12-24 00:26:36 +00:00
void init_drivers ( void )
{
init_video_input ( ) ;
init_audio ( ) ;
}
void uninit_drivers ( void )
{
uninit_audio ( ) ;
2011-12-25 18:31:05 +00:00
uninit_video_input ( ) ;
2010-12-24 00:26:36 +00:00
}
2011-12-01 21:36:26 +00:00
# ifdef HAVE_DYLIB
2011-05-13 19:05:28 +00:00
static void init_dsp_plugin ( void )
{
if ( ! ( * g_settings . audio . dsp_plugin ) )
return ;
2012-07-06 15:36:37 +00:00
# ifdef HAVE_FIXED_POINT
RARCH_WARN ( " DSP plugins are not available in fixed point mode. \n " ) ;
# else
2012-04-21 21:25:32 +00:00
rarch_dsp_info_t info = { 0 } ;
2011-05-13 19:05:28 +00:00
g_extern . audio_data . dsp_lib = dylib_load ( g_settings . audio . dsp_plugin ) ;
if ( ! g_extern . audio_data . dsp_lib )
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to open DSP plugin: \" %s \" ... \n " , g_settings . audio . dsp_plugin ) ;
2011-05-13 19:05:28 +00:00
return ;
}
2012-04-21 21:25:32 +00:00
const rarch_dsp_plugin_t * ( RARCH_API_CALLTYPE * plugin_init ) ( void ) =
( const rarch_dsp_plugin_t * ( RARCH_API_CALLTYPE * ) ( void ) ) dylib_proc ( g_extern . audio_data . dsp_lib , " rarch_dsp_plugin_init " ) ;
2012-04-21 21:36:55 +00:00
if ( ! plugin_init )
plugin_init = ( const rarch_dsp_plugin_t * ( RARCH_API_CALLTYPE * ) ( void ) ) dylib_proc ( g_extern . audio_data . dsp_lib , " ssnes_dsp_plugin_init " ) ; // Compat. Will be dropped on ABI break.
2011-05-13 19:05:28 +00:00
if ( ! plugin_init )
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to find symbol \" rarch_dsp_plugin_init \" in DSP plugin. \n " ) ;
2011-05-13 19:22:37 +00:00
goto error ;
2011-05-13 19:05:28 +00:00
}
g_extern . audio_data . dsp_plugin = plugin_init ( ) ;
if ( ! g_extern . audio_data . dsp_plugin )
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to get a valid DSP plugin. \n " ) ;
2011-05-13 19:22:37 +00:00
goto error ;
}
2012-04-21 21:25:32 +00:00
if ( g_extern . audio_data . dsp_plugin - > api_version ! = RARCH_DSP_API_VERSION )
2011-05-13 19:22:37 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " DSP plugin API mismatch. SSNES: %d, Plugin: %d \n " , RARCH_DSP_API_VERSION , g_extern . audio_data . dsp_plugin - > api_version ) ;
2011-05-13 19:22:37 +00:00
goto error ;
2011-05-13 19:05:28 +00:00
}
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Loaded DSP plugin: \" %s \" \n " , g_extern . audio_data . dsp_plugin - > ident ? g_extern . audio_data . dsp_plugin - > ident : " Unknown " ) ;
2011-05-17 17:20:41 +00:00
2011-12-24 12:46:12 +00:00
info . input_rate = g_settings . audio . in_rate ;
info . output_rate = g_settings . audio . out_rate ;
2011-05-13 19:22:37 +00:00
2011-05-13 19:05:28 +00:00
g_extern . audio_data . dsp_handle = g_extern . audio_data . dsp_plugin - > init ( & info ) ;
if ( ! g_extern . audio_data . dsp_handle )
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to init DSP plugin. \n " ) ;
2011-05-13 19:22:37 +00:00
goto error ;
2011-05-13 19:05:28 +00:00
}
2011-05-13 19:22:37 +00:00
return ;
error :
if ( g_extern . audio_data . dsp_lib )
dylib_close ( g_extern . audio_data . dsp_lib ) ;
g_extern . audio_data . dsp_plugin = NULL ;
g_extern . audio_data . dsp_lib = NULL ;
2012-07-06 15:36:37 +00:00
# endif
2011-05-13 19:05:28 +00:00
}
static void deinit_dsp_plugin ( void )
{
if ( g_extern . audio_data . dsp_lib & & g_extern . audio_data . dsp_plugin )
{
g_extern . audio_data . dsp_plugin - > free ( g_extern . audio_data . dsp_handle ) ;
dylib_close ( g_extern . audio_data . dsp_lib ) ;
}
}
2011-12-01 21:36:26 +00:00
# endif
2011-05-13 19:05:28 +00:00
2011-11-18 14:14:56 +00:00
static void adjust_audio_input_rate ( void )
{
2012-04-07 09:55:37 +00:00
const struct retro_system_timing * info = & g_extern . system . av_info . timing ;
float timing_skew = fabs ( 1.0f - info - > fps / g_settings . video . refresh_rate ) ;
if ( timing_skew > 0.05f ) // We don't want to adjust pitch too much. If we have extreme cases, just don't readjust at all.
2011-11-19 13:16:55 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Timings deviate too much. Will not adjust. (Display = %.2f Hz, Game = %.2f Hz) \n " ,
2012-04-07 09:55:37 +00:00
g_settings . video . refresh_rate ,
( float ) info - > fps ) ;
2011-11-19 13:16:55 +00:00
2012-04-07 09:55:37 +00:00
g_settings . video . refresh_rate = info - > fps ;
2011-11-19 13:16:55 +00:00
}
2012-04-07 09:55:37 +00:00
g_settings . audio . in_rate = info - > sample_rate *
( g_settings . video . refresh_rate / info - > fps ) ;
2011-11-18 14:14:56 +00:00
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Set audio input rate to: %.2f Hz. \n " , g_settings . audio . in_rate ) ;
2011-11-18 14:14:56 +00:00
}
2010-12-24 00:26:36 +00:00
void init_audio ( void )
{
2011-11-20 01:06:25 +00:00
// Accomodate rewind since at some point we might have two full buffers.
size_t max_bufsamples = AUDIO_CHUNK_SIZE_NONBLOCKING * 2 ;
2012-03-04 12:19:51 +00:00
size_t outsamples_max = max_bufsamples * AUDIO_MAX_RATIO * g_settings . slowmotion_ratio ;
2011-11-20 01:06:25 +00:00
// Used for recording even if audio isn't enabled.
2012-04-21 21:25:32 +00:00
rarch_assert ( g_extern . audio_data . conv_outsamples = ( int16_t * ) malloc ( outsamples_max * sizeof ( int16_t ) ) ) ;
2012-01-14 22:15:25 +00:00
2012-07-06 15:36:37 +00:00
g_extern . audio_data . block_chunk_size = AUDIO_CHUNK_SIZE_BLOCKING ;
2012-01-14 22:15:25 +00:00
g_extern . audio_data . nonblock_chunk_size = AUDIO_CHUNK_SIZE_NONBLOCKING ;
2012-07-06 15:36:37 +00:00
g_extern . audio_data . chunk_size = g_extern . audio_data . block_chunk_size ;
2011-11-20 01:06:25 +00:00
// Needs to be able to hold full content of a full max_bufsamples in addition to its own.
2012-04-21 21:25:32 +00:00
rarch_assert ( g_extern . audio_data . rewind_buf = ( int16_t * ) malloc ( max_bufsamples * sizeof ( int16_t ) ) ) ;
2012-07-06 15:36:37 +00:00
g_extern . audio_data . rewind_size = max_bufsamples ;
2011-11-20 01:06:25 +00:00
2010-12-29 18:43:17 +00:00
if ( ! g_settings . audio . enable )
2010-12-24 00:26:36 +00:00
{
2010-12-29 18:18:37 +00:00
g_extern . audio_active = false ;
2010-12-24 00:26:36 +00:00
return ;
}
2011-11-18 14:14:56 +00:00
adjust_audio_input_rate ( ) ;
2010-12-29 19:50:50 +00:00
2012-03-28 22:30:50 +00:00
driver . audio_data = audio_init_func ( * g_settings . audio . device ? g_settings . audio . device : NULL ,
2011-11-20 01:06:25 +00:00
g_settings . audio . out_rate , g_settings . audio . latency ) ;
2011-10-15 10:48:15 +00:00
if ( ! driver . audio_data )
2012-04-19 19:09:27 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to initialize audio driver. Will continue without audio. \n " ) ;
2010-12-29 18:18:37 +00:00
g_extern . audio_active = false ;
2012-04-19 19:09:27 +00:00
}
2010-12-24 00:26:36 +00:00
2012-03-28 22:30:50 +00:00
if ( g_extern . audio_active & & driver . audio - > use_float & & audio_use_float_func ( ) )
2011-01-15 19:37:42 +00:00
g_extern . audio_data . use_float = true ;
2011-01-14 14:34:38 +00:00
2012-07-06 16:15:14 +00:00
# ifdef HAVE_FIXED_POINT
if ( g_extern . audio_data . use_float )
{
uninit_audio ( ) ;
RARCH_ERR ( " RetroArch is configured for fixed point, but audio driver demands floating point. Will disable audio. \n " ) ;
g_extern . audio_active = false ;
}
# endif
2010-12-29 18:43:17 +00:00
if ( ! g_settings . audio . sync & & g_extern . audio_active )
2011-01-14 14:34:38 +00:00
{
2012-03-28 22:30:50 +00:00
audio_set_nonblock_state_func ( true ) ;
2011-01-14 14:34:38 +00:00
g_extern . audio_data . chunk_size = g_extern . audio_data . nonblock_chunk_size ;
}
2010-12-24 00:26:36 +00:00
2012-02-23 22:19:23 +00:00
g_extern . audio_data . source = resampler_new ( ) ;
2011-02-06 12:29:48 +00:00
if ( ! g_extern . audio_data . source )
g_extern . audio_active = false ;
2011-01-14 14:34:38 +00:00
2012-07-06 15:36:37 +00:00
# ifndef HAVE_FIXED_POINT
2012-04-21 21:25:32 +00:00
rarch_assert ( g_extern . audio_data . data = ( float * ) malloc ( max_bufsamples * sizeof ( float ) ) ) ;
2012-07-06 15:36:37 +00:00
# endif
2011-01-14 14:34:38 +00:00
g_extern . audio_data . data_ptr = 0 ;
2011-12-25 10:45:27 +00:00
2012-04-21 21:25:32 +00:00
rarch_assert ( g_settings . audio . out_rate < g_settings . audio . in_rate * AUDIO_MAX_RATIO ) ;
2012-07-06 15:36:37 +00:00
rarch_assert ( g_extern . audio_data . outsamples = ( sample_t * ) malloc ( outsamples_max * sizeof ( sample_t ) ) ) ;
2011-10-15 12:33:41 +00:00
2012-02-14 00:16:37 +00:00
g_extern . audio_data . orig_src_ratio =
g_extern . audio_data . src_ratio =
2011-10-15 14:16:13 +00:00
( double ) g_settings . audio . out_rate / g_settings . audio . in_rate ;
2012-04-19 19:09:27 +00:00
if ( g_extern . audio_active & & g_settings . audio . rate_control )
2012-02-14 00:16:37 +00:00
{
if ( driver . audio - > buffer_size & & driver . audio - > write_avail )
{
2012-03-28 22:30:50 +00:00
g_extern . audio_data . driver_buffer_size = audio_buffer_size_func ( ) ;
2012-02-14 00:16:37 +00:00
g_extern . audio_data . rate_control = true ;
}
else
2012-04-21 21:25:32 +00:00
RARCH_WARN ( " Audio rate control was desired, but driver does not support needed features. \n " ) ;
2012-02-14 00:16:37 +00:00
}
2011-12-01 21:36:26 +00:00
# ifdef HAVE_DYLIB
2011-05-13 19:05:28 +00:00
init_dsp_plugin ( ) ;
2011-12-01 21:36:26 +00:00
# endif
2010-12-24 00:26:36 +00:00
}
void uninit_audio ( void )
{
2011-12-25 18:31:05 +00:00
free ( g_extern . audio_data . conv_outsamples ) ;
g_extern . audio_data . conv_outsamples = NULL ;
2012-07-06 15:36:37 +00:00
g_extern . audio_data . data_ptr = 0 ;
2011-12-25 18:31:05 +00:00
2011-11-20 01:06:25 +00:00
free ( g_extern . audio_data . rewind_buf ) ;
g_extern . audio_data . rewind_buf = NULL ;
2010-12-29 18:43:17 +00:00
if ( ! g_settings . audio . enable )
2010-12-24 00:26:36 +00:00
{
2010-12-29 18:18:37 +00:00
g_extern . audio_active = false ;
2010-12-24 00:26:36 +00:00
return ;
}
2011-10-15 10:48:15 +00:00
if ( driver . audio_data & & driver . audio )
2010-12-24 00:26:36 +00:00
driver . audio - > free ( driver . audio_data ) ;
2011-10-15 10:48:15 +00:00
if ( g_extern . audio_data . source )
2012-02-23 22:19:23 +00:00
resampler_free ( g_extern . audio_data . source ) ;
2011-01-14 14:34:38 +00:00
2012-07-06 15:36:37 +00:00
# ifndef HAVE_FIXED_POINT
2011-11-20 01:06:25 +00:00
free ( g_extern . audio_data . data ) ;
g_extern . audio_data . data = NULL ;
2012-07-06 15:36:37 +00:00
# endif
2011-12-25 18:31:05 +00:00
2011-11-20 01:06:25 +00:00
free ( g_extern . audio_data . outsamples ) ;
g_extern . audio_data . outsamples = NULL ;
2011-05-13 19:05:28 +00:00
2011-12-01 21:36:26 +00:00
# ifdef HAVE_DYLIB
2011-05-13 19:05:28 +00:00
deinit_dsp_plugin ( ) ;
2011-12-01 21:36:26 +00:00
# endif
2010-12-24 00:26:36 +00:00
}
2011-05-11 15:52:16 +00:00
# ifdef HAVE_DYLIB
2011-03-07 18:12:14 +00:00
static void init_filter ( void )
2010-12-24 00:26:36 +00:00
{
2011-03-07 18:12:14 +00:00
if ( g_extern . filter . active )
return ;
if ( * g_settings . video . filter_path = = ' \0 ' )
return ;
2010-12-24 00:26:36 +00:00
2012-06-16 13:07:31 +00:00
if ( g_extern . system . rgb32 )
{
RARCH_WARN ( " libretro implementation uses XRGB8888 format. CPU filters only support 0RGB1555. \n " ) ;
return ;
}
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Loading bSNES filter from \" %s \" \n " , g_settings . video . filter_path ) ;
2011-03-07 18:12:14 +00:00
g_extern . filter . lib = dylib_load ( g_settings . video . filter_path ) ;
if ( ! g_extern . filter . lib )
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to load filter \" %s \" \n " , g_settings . video . filter_path ) ;
2011-03-07 18:12:14 +00:00
return ;
}
2010-12-29 19:50:50 +00:00
2011-05-31 13:03:59 +00:00
g_extern . filter . psize =
( void ( * ) ( unsigned * , unsigned * ) ) dylib_proc ( g_extern . filter . lib , " filter_size " ) ;
g_extern . filter . prender =
( void ( * ) ( uint32_t * , uint32_t * ,
unsigned , const uint16_t * ,
unsigned , unsigned , unsigned ) ) dylib_proc ( g_extern . filter . lib , " filter_render " ) ;
2012-06-17 22:34:47 +00:00
2011-03-07 18:12:14 +00:00
if ( ! g_extern . filter . psize | | ! g_extern . filter . prender )
2010-12-30 00:33:40 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Failed to find functions in filter... \n " ) ;
2011-03-07 18:12:14 +00:00
dylib_close ( g_extern . filter . lib ) ;
g_extern . filter . lib = NULL ;
return ;
2010-12-30 00:33:40 +00:00
}
2011-03-07 18:12:14 +00:00
g_extern . filter . active = true ;
2012-04-07 09:55:37 +00:00
struct retro_game_geometry * geom = & g_extern . system . av_info . geometry ;
2012-06-17 22:34:47 +00:00
unsigned width = geom - > max_width ;
2012-04-07 09:55:37 +00:00
unsigned height = geom - > max_height ;
2011-03-07 18:12:14 +00:00
g_extern . filter . psize ( & width , & height ) ;
2012-06-17 22:34:47 +00:00
unsigned pow2_x = next_pow2 ( width ) ;
unsigned pow2_y = next_pow2 ( height ) ;
2011-03-07 18:12:14 +00:00
unsigned maxsize = pow2_x > pow2_y ? pow2_x : pow2_y ;
2012-04-21 21:25:32 +00:00
g_extern . filter . scale = maxsize / RARCH_SCALE_BASE ;
2011-03-07 18:12:14 +00:00
2012-06-17 22:34:47 +00:00
g_extern . filter . buffer = ( uint32_t * ) malloc ( RARCH_SCALE_BASE * RARCH_SCALE_BASE *
g_extern . filter . scale * g_extern . filter . scale * sizeof ( uint32_t ) ) ;
2012-04-21 21:25:32 +00:00
rarch_assert ( g_extern . filter . buffer ) ;
2011-03-07 18:12:14 +00:00
2012-06-17 22:34:47 +00:00
g_extern . filter . pitch = RARCH_SCALE_BASE * g_extern . filter . scale * sizeof ( uint32_t ) ;
g_extern . filter . colormap = ( uint32_t * ) malloc ( 0x10000 * sizeof ( uint32_t ) ) ;
2012-04-21 21:25:32 +00:00
rarch_assert ( g_extern . filter . colormap ) ;
2011-03-07 18:12:14 +00:00
2011-05-28 12:11:37 +00:00
// Set up conversion map from 16-bit XRGB1555 to 32-bit ARGB.
2012-06-17 22:34:47 +00:00
for ( unsigned i = 0 ; i < 0x10000 ; i + + )
2011-03-07 18:12:14 +00:00
{
2012-06-17 22:34:47 +00:00
unsigned r = ( i > > 10 ) & 0x1f ;
unsigned g = ( i > > 5 ) & 0x1f ;
unsigned b = ( i > > 0 ) & 0x1f ;
2011-03-07 18:12:14 +00:00
r = ( r < < 3 ) | ( r > > 2 ) ;
g = ( g < < 3 ) | ( g > > 2 ) ;
b = ( b < < 3 ) | ( b > > 2 ) ;
2011-05-28 12:11:37 +00:00
g_extern . filter . colormap [ i ] = ( r < < 16 ) | ( g < < 8 ) | ( b < < 0 ) ;
2011-03-07 18:12:14 +00:00
}
}
static void deinit_filter ( void )
{
2012-03-12 20:45:43 +00:00
if ( ! g_extern . filter . active )
return ;
g_extern . filter . active = false ;
dylib_close ( g_extern . filter . lib ) ;
g_extern . filter . lib = NULL ;
free ( g_extern . filter . buffer ) ;
free ( g_extern . filter . colormap ) ;
2011-03-07 18:12:14 +00:00
}
2011-12-01 20:54:42 +00:00
# endif
2011-03-07 18:12:14 +00:00
2011-03-29 17:15:02 +00:00
# ifdef HAVE_XML
2012-06-23 13:31:22 +00:00
static void deinit_shader_dir ( void )
{
// It handles NULL, no worries :D
dir_list_free ( g_extern . shader_dir . list ) ;
g_extern . shader_dir . list = NULL ;
g_extern . shader_dir . ptr = 0 ;
}
2011-03-29 16:04:41 +00:00
static void init_shader_dir ( void )
{
if ( ! * g_settings . video . shader_dir )
return ;
2012-06-23 13:31:22 +00:00
g_extern . shader_dir . list = dir_list_new ( g_settings . video . shader_dir , " shader " , false ) ;
if ( g_extern . shader_dir . list - > size = = 0 )
{
deinit_shader_dir ( ) ;
return ;
}
2012-06-17 23:11:03 +00:00
2012-06-23 13:31:22 +00:00
g_extern . shader_dir . ptr = 0 ;
dir_list_sort ( g_extern . shader_dir . list , false ) ;
2011-03-29 16:04:41 +00:00
2012-06-23 13:31:22 +00:00
for ( unsigned i = 0 ; i < g_extern . shader_dir . list - > size ; i + + )
RARCH_LOG ( " Found shader \" %s \" \n " , g_extern . shader_dir . list - > elems [ i ] . data ) ;
2011-03-29 16:04:41 +00:00
}
2011-03-29 17:15:02 +00:00
# endif
2011-03-29 16:04:41 +00:00
2011-03-07 18:12:14 +00:00
void init_video_input ( void )
{
2011-05-11 15:52:16 +00:00
# ifdef HAVE_DYLIB
2011-03-07 18:12:14 +00:00
init_filter ( ) ;
2010-12-29 18:43:17 +00:00
# endif
2010-12-24 00:26:36 +00:00
2011-03-29 16:04:41 +00:00
# ifdef HAVE_XML
init_shader_dir ( ) ;
# endif
2012-04-09 20:19:51 +00:00
const struct retro_game_geometry * geom = & g_extern . system . av_info . geometry ;
2012-04-07 09:55:37 +00:00
unsigned max_dim = max ( geom - > max_width , geom - > max_height ) ;
2012-04-21 21:25:32 +00:00
unsigned scale = next_pow2 ( max_dim ) / RARCH_SCALE_BASE ;
2011-10-27 21:40:34 +00:00
scale = max ( scale , 1 ) ;
2011-03-07 18:12:14 +00:00
if ( g_extern . filter . active )
scale = g_extern . filter . scale ;
2012-04-15 19:48:01 +00:00
if ( g_settings . video . aspect_ratio < 0.0f )
{
if ( geom - > aspect_ratio > 0.0f & & g_settings . video . aspect_ratio_auto )
g_settings . video . aspect_ratio = geom - > aspect_ratio ;
else
g_settings . video . aspect_ratio = ( float ) geom - > base_width / geom - > base_height ; // 1:1 PAR.
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Adjusting aspect ratio to %.2f \n " , g_settings . video . aspect_ratio ) ;
2012-04-15 19:48:01 +00:00
}
2011-05-05 09:38:57 +00:00
unsigned width ;
unsigned height ;
if ( g_settings . video . fullscreen )
{
width = g_settings . video . fullscreen_x ;
height = g_settings . video . fullscreen_y ;
}
else
{
2012-04-15 19:48:01 +00:00
if ( g_settings . video . force_aspect )
2011-05-05 09:38:57 +00:00
{
2012-04-07 09:55:37 +00:00
width = roundf ( geom - > base_height * g_settings . video . xscale * g_settings . video . aspect_ratio ) ;
height = roundf ( geom - > base_height * g_settings . video . yscale ) ;
2011-05-05 09:38:57 +00:00
}
else
{
2012-04-07 09:55:37 +00:00
width = roundf ( geom - > base_width * g_settings . video . xscale ) ;
height = roundf ( geom - > base_height * g_settings . video . yscale ) ;
2011-05-05 09:38:57 +00:00
}
}
2012-04-21 21:25:32 +00:00
RARCH_LOG ( " Video @ %ux%u \n " , width , height ) ;
2011-10-27 21:40:34 +00:00
2011-12-24 12:46:12 +00:00
video_info_t video = { 0 } ;
video . width = width ;
video . height = height ;
video . fullscreen = g_settings . video . fullscreen ;
video . vsync = g_settings . video . vsync ;
video . force_aspect = g_settings . video . force_aspect ;
video . smooth = g_settings . video . smooth ;
video . input_scale = scale ;
2012-06-16 13:07:31 +00:00
video . rgb32 = g_extern . filter . active | | g_extern . system . rgb32 ;
2010-12-24 00:26:36 +00:00
const input_driver_t * tmp = driver . input ;
2012-03-28 22:30:50 +00:00
driver . video_data = video_init_func ( & video , & driver . input , & driver . input_data ) ;
2010-12-24 00:26:36 +00:00
2011-09-20 09:58:21 +00:00
if ( driver . video_data = = NULL )
2010-12-24 00:26:36 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Cannot open video driver ... Exiting ... \n " ) ;
rarch_fail ( 1 , " init_video_input() " ) ;
2010-12-24 00:26:36 +00:00
}
2012-04-01 17:20:37 +00:00
if ( driver . video - > set_rotation & & g_extern . system . rotation )
video_set_rotation_func ( g_extern . system . rotation ) ;
2011-01-06 19:01:32 +00:00
// Video driver didn't provide an input driver so we use configured one.
if ( driver . input = = NULL )
2010-12-24 00:26:36 +00:00
{
driver . input = tmp ;
if ( driver . input ! = NULL )
{
2012-03-28 22:30:50 +00:00
driver . input_data = input_init_func ( ) ;
2011-09-20 09:58:21 +00:00
if ( driver . input_data = = NULL )
2011-01-06 17:34:11 +00:00
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Cannot init input driver. Exiting ... \n " ) ;
rarch_fail ( 1 , " init_video_input() " ) ;
2011-01-06 17:34:11 +00:00
}
2010-12-24 00:26:36 +00:00
}
else
{
2012-04-21 21:25:32 +00:00
RARCH_ERR ( " Cannot find input driver. Exiting ... \n " ) ;
rarch_fail ( 1 , " init_video_input() " ) ;
2010-12-24 00:26:36 +00:00
}
}
}
void uninit_video_input ( void )
{
2011-09-20 09:58:21 +00:00
if ( driver . input_data ! = driver . video_data & & driver . input )
2012-03-28 22:30:50 +00:00
input_free_func ( ) ;
2011-03-07 18:56:40 +00:00
2011-09-20 09:58:21 +00:00
if ( driver . video_data & & driver . video )
2012-03-28 22:30:50 +00:00
video_free_func ( ) ;
2011-08-08 22:11:09 +00:00
2011-12-01 20:54:42 +00:00
# ifdef HAVE_DYLIB
2011-03-07 18:56:40 +00:00
deinit_filter ( ) ;
2011-12-01 20:54:42 +00:00
# endif
2011-03-29 16:04:41 +00:00
# ifdef HAVE_XML
deinit_shader_dir ( ) ;
# endif
2010-12-24 00:26:36 +00:00
}
2010-12-29 19:05:57 +00:00
driver_t driver ;