From 7777d54887d95a38cd0222233ca06d8a146e5a76 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 1 Jun 2007 22:26:12 +0000 Subject: 2nd stage of denormal handling (from trunk); fix to avoid FLAC support when using a too-new FLAC library git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@1940 d708f5d6-7413-0410-9779-e7cbd77b26cf --- SConstruct | 9 ++++- gtk2_ardour/ardour.menus | 23 ++++++----- gtk2_ardour/ardour_ui_ed.cc | 19 +++++++-- libs/ardour/globals.cc | 62 +++++++++-------------------- libs/ardour/session_state.cc | 2 + libs/pbd/SConscript | 1 + libs/pbd/fpu.cc | 92 ++++++++++++++++++++++++++++++++++++++++++++ libs/pbd/pbd/fpu.h | 31 +++++++++++++++ 8 files changed, 181 insertions(+), 58 deletions(-) create mode 100644 libs/pbd/fpu.cc create mode 100644 libs/pbd/pbd/fpu.h diff --git a/SConstruct b/SConstruct index 15e4f1e9ca..4d0b6ef677 100644 --- a/SConstruct +++ b/SConstruct @@ -36,7 +36,6 @@ opts.AddOptions( BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0), BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 0), BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1), - BoolOption('USE_XMMINTRIN', 'Use gcc XMM intrinsics where possible', 1), BoolOption('LIBLO', 'Compile with support for liblo library', 1), BoolOption('NLS', 'Set to turn on i18n support', 1), PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'), @@ -736,8 +735,14 @@ libraries['flac'] = LibraryInfo () prep_libcheck(env, libraries['flac']) libraries['flac'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local/lib") +# +# june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions +# since the version of libsndfile we have internally does not support +# the new API that libFLAC has adopted +# + conf = Configure (libraries['flac']) -if conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new', language='CXX'): +if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_set_read_callback', language='CXX'): conf.env.Append(CCFLAGS='-DHAVE_FLAC') libraries['flac'] = conf.Finish () diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index bd4bb3a0a1..b8c98bc7a9 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -333,9 +333,17 @@ - - - + + + + + + + + + + + @@ -353,13 +361,8 @@ - - - - - - - + + diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 37e23cdf6e..0e54e6253e 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -24,6 +24,7 @@ */ #include +#include #include @@ -413,11 +414,23 @@ ARDOUR_UI::install_actions () RadioAction::Group denormal_group; ActionManager::register_toggle_action (option_actions, X_("DenormalProtection"), _("Use DC bias"), mem_fun (*this, &ARDOUR_UI::toggle_denormal_protection)); + + FPU fpu; ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalNone"), _("No processor handling"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalNone)); - ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZ"), _("Use FlushToZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZ)); - ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalDAZ"), _("Use DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalDAZ)); - ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ)); + + act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZ"), _("Use FlushToZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZ)); + if (!fpu.has_flush_to_zero()) { + act->set_sensitive (false); + } + act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalDAZ"), _("Use DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalDAZ)); + if (!fpu.has_denormals_are_zero()) { + act->set_sensitive (false); + } + act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ)); + if (!fpu.has_flush_to_zero() || !fpu.has_denormals_are_zero()) { + act->set_sensitive (false); + } act = ActionManager::register_toggle_action (option_actions, X_("DoNotRunPluginsWhileRecording"), _("Do not run plugins while recording"), mem_fun (*this, &ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording)); ActionManager::session_sensitive_actions.push_back (act); diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index eb5a2cc9f2..a6fb0fcf41 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -200,42 +201,14 @@ void setup_hardware_optimization (bool try_optimization) { bool generic_mix_functions = true; - + FPU fpu; if (try_optimization) { #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS) - - unsigned long use_sse = 0; - -#ifndef USE_X86_64_ASM - asm ( - "mov $1, %%eax\n" - "pushl %%ebx\n" - "cpuid\n" - "movl %%edx, %0\n" - "popl %%ebx\n" - : "=r" (use_sse) - : - : "%eax", "%ecx", "%edx", "memory"); - -#else - - asm ( - "pushq %%rbx\n" - "movq $1, %%rax\n" - "cpuid\n" - "movq %%rdx, %0\n" - "popq %%rbx\n" - : "=r" (use_sse) - : - : "%rax", "%rcx", "%rdx", "memory"); - -#endif /* USE_X86_64_ASM */ - - use_sse &= (1 << 25); // bit 25 = SSE support + + if (fpu.has_sse()) { - if (use_sse) { info << "Using SSE optimized routines" << endmsg; // SSE SET @@ -538,17 +511,16 @@ ARDOUR::LocaleGuard::~LocaleGuard () void ARDOUR::setup_fpu () { -#ifdef USE_XMMINTRIN +#if defined(ARCH_X86) && defined(USE_XMMINTRIN) + int MXCSR; + FPU fpu; /* XXX use real code to determine if the processor supports DenormalsAreZero and FlushToZero */ - bool has_daz = false; - bool can_ftz = true; - - if (!can_ftz && !has_daz) { + if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) { return; } @@ -556,25 +528,29 @@ ARDOUR::setup_fpu () switch (Config->get_denormal_model()) { case DenormalNone: - MXCSR &= ~_MM_FLUSH_ZERO_ON; + MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000); break; case DenormalFTZ: - MXCSR |= _MM_FLUSH_ZERO_ON; + if (fpu.has_flush_to_zero()) { + MXCSR |= _MM_FLUSH_ZERO_ON; + } break; case DenormalDAZ: MXCSR &= ~_MM_FLUSH_ZERO_ON; - if (has_daz) { + if (fpu.has_denormals_are_zero()) { MXCSR |= 0x8000; } break; case DenormalFTZDAZ: - if (has_daz) { - MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000; - } else { - MXCSR |= _MM_FLUSH_ZERO_ON; + if (fpu.has_flush_to_zero()) { + if (fpu.has_denormals_are_zero()) { + MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000; + } else { + MXCSR |= _MM_FLUSH_ZERO_ON; + } } break; } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 937fd78daf..37b717f491 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3278,6 +3278,8 @@ Session::config_changed (const char* parameter_name) set_slave_source (Config->get_slave_source()); } else if (PARAM_IS ("remote-model")) { set_remote_control_ids (); + } else if (PARAM_IS ("denormal-model")) { + setup_fpu (); } set_dirty (); diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript index 3aaeb1bf1b..a0065f09bd 100644 --- a/libs/pbd/SConscript +++ b/libs/pbd/SConscript @@ -27,6 +27,7 @@ controllable.cc enumwriter.cc dmalloc.cc error.cc +fpu.cc id.cc mountpoint.cc path.cc diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc new file mode 100644 index 0000000000..ae69b62e8d --- /dev/null +++ b/libs/pbd/fpu.cc @@ -0,0 +1,92 @@ +#define _XOPEN_SOURCE 600 +#include +#include + +#include +#include + +#include "i18n.h" + +using namespace PBD; +using namespace std; + +FPU::FPU () +{ + unsigned long cpuflags = 0; + + _flags = Flags (0); + +#ifndef ARCH_X86 + return; +#endif + +#ifndef USE_X86_64_ASM + asm volatile ( + "mov $1, %%eax\n" + "pushl %%ebx\n" + "cpuid\n" + "movl %%edx, %0\n" + "popl %%ebx\n" + : "=r" (cpuflags) + : + : "%eax", "%ecx", "%edx", "memory" + ); + +#else + + asm volatile ( + "pushq %%rbx\n" + "movq $1, %%rax\n" + "cpuid\n" + "movq %%rdx, %0\n" + "popq %%rbx\n" + : "=r" (cpuflags) + : + : "%rax", "%rcx", "%rdx", "memory" + ); + +#endif /* USE_X86_64_ASM */ + + if (cpuflags & (1<<25)) { + _flags = Flags (_flags | (HasSSE|HasFlushToZero)); + } + + if (cpuflags & (1<<26)) { + _flags = Flags (_flags | HasSSE2); + } + + if (cpuflags & (1 << 24)) { + + char* fxbuf = 0; + + if (posix_memalign ((void**)&fxbuf, 16, 512)) { + error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg; + } else { + + asm volatile ( + "fxsave (%0)" + : + : "r" (fxbuf) + : "memory" + ); + + uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]); + + /* if the mask is zero, set its default value (from intel specs) */ + + if (mxcsr_mask == 0) { + mxcsr_mask = 0xffbf; + } + + if (mxcsr_mask & (1<<6)) { + _flags = Flags (_flags | HasDenormalsAreZero); + } + + free (fxbuf); + } + } +} + +FPU::~FPU () +{ +} diff --git a/libs/pbd/pbd/fpu.h b/libs/pbd/pbd/fpu.h new file mode 100644 index 0000000000..617dcdf3da --- /dev/null +++ b/libs/pbd/pbd/fpu.h @@ -0,0 +1,31 @@ +#ifndef __pbd_fpu_h__ +#define __pbd_fpu_h__ + +namespace PBD { + + +class FPU { + private: + enum Flags { + HasFlushToZero = 0x1, + HasDenormalsAreZero = 0x2, + HasSSE = 0x4, + HasSSE2 = 0x8 + }; + + public: + FPU (); + ~FPU (); + + bool has_flush_to_zero () const { return _flags & HasFlushToZero; } + bool has_denormals_are_zero () const { return _flags & HasDenormalsAreZero; } + bool has_sse () const { return _flags & HasSSE; } + bool has_sse2 () const { return _flags & HasSSE2; } + + private: + Flags _flags; +}; + +} + +#endif /* __pbd_fpu_h__ */ -- cgit v1.2.3