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
This commit is contained in:
Paul Davis 2007-06-01 22:26:12 +00:00
parent 2291d59bc8
commit 7777d54887
8 changed files with 181 additions and 58 deletions

View file

@ -36,7 +36,6 @@ opts.AddOptions(
BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0), BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0),
BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 0), BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 0),
BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1), 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('LIBLO', 'Compile with support for liblo library', 1),
BoolOption('NLS', 'Set to turn on i18n support', 1), BoolOption('NLS', 'Set to turn on i18n support', 1),
PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'), PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
@ -736,8 +735,14 @@ libraries['flac'] = LibraryInfo ()
prep_libcheck(env, libraries['flac']) prep_libcheck(env, libraries['flac'])
libraries['flac'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local/lib") 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']) 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') conf.env.Append(CCFLAGS='-DHAVE_FLAC')
libraries['flac'] = conf.Finish () libraries['flac'] = conf.Finish ()

View file

@ -333,9 +333,17 @@
<menuitem action='CrossfadesShort'/> <menuitem action='CrossfadesShort'/>
</menu> </menu>
<menu action='Layering'> <menu action='Layering'>
<menuitem action='LayerLaterHigher'/> <menuitem action='LayerLaterHigher'/>
<menuitem action='LayerMoveAddHigher'/> <menuitem action='LayerMoveAddHigher'/>
<menuitem action='LayerAddHigher'/> <menuitem action='LayerAddHigher'/>
</menu>
<menu name='Denormals' action='Denormals'>
<menuitem action='DenormalProtection'/>
<separator/>
<menuitem action='DenormalNone'/>
<menuitem action='DenormalFTZ'/>
<menuitem action='DenormalDAZ'/>
<menuitem action='DenormalFTZDAZ'/>
</menu> </menu>
<separator/> <separator/>
<menuitem action='SendMTC'/> <menuitem action='SendMTC'/>
@ -353,13 +361,8 @@
<menuitem action='StopRecordingOnXrun'/> <menuitem action='StopRecordingOnXrun'/>
<menuitem action='StopTransportAtEndOfSession'/> <menuitem action='StopTransportAtEndOfSession'/>
<menuitem action='GainReduceFastTransport'/> <menuitem action='GainReduceFastTransport'/>
<menu name='Denormals' action='Denormals'> <menuitem action='PrimaryClockDeltaEditCursor'/>
<menuitem action='DenormalProtection'/> <menuitem action='SecondaryClockDeltaEditCursor'/>
<menuitem action='DenormalNone'/>
<menuitem action='DenormalFTZ'/>
<menuitem action='DenormalDAZ'/>
<menuitem action='DenormalFTZDAZ'/>
</menu>
</menu> </menu>
<menu name='Help' action='Help'> <menu name='Help' action='Help'>
<menuitem action='About'/> <menuitem action='About'/>

View file

@ -24,6 +24,7 @@
*/ */
#include <pbd/pathscanner.h> #include <pbd/pathscanner.h>
#include <pbd/fpu.h>
#include <glibmm/miscutils.h> #include <glibmm/miscutils.h>
@ -413,11 +414,23 @@ ARDOUR_UI::install_actions ()
RadioAction::Group denormal_group; RadioAction::Group denormal_group;
ActionManager::register_toggle_action (option_actions, X_("DenormalProtection"), _("Use DC bias"), mem_fun (*this, &ARDOUR_UI::toggle_denormal_protection)); 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_("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)); act = 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_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ)); 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)); 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); ActionManager::session_sensitive_actions.push_back (act);

View file

@ -37,6 +37,7 @@
#include <pbd/error.h> #include <pbd/error.h>
#include <pbd/id.h> #include <pbd/id.h>
#include <pbd/strsplit.h> #include <pbd/strsplit.h>
#include <pbd/fpu.h>
#include <midi++/port.h> #include <midi++/port.h>
#include <midi++/port_request.h> #include <midi++/port_request.h>
@ -200,42 +201,14 @@ void
setup_hardware_optimization (bool try_optimization) setup_hardware_optimization (bool try_optimization)
{ {
bool generic_mix_functions = true; bool generic_mix_functions = true;
FPU fpu;
if (try_optimization) { if (try_optimization) {
#if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS) #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
unsigned long use_sse = 0; if (fpu.has_sse()) {
#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 (use_sse) {
info << "Using SSE optimized routines" << endmsg; info << "Using SSE optimized routines" << endmsg;
// SSE SET // SSE SET
@ -538,17 +511,16 @@ ARDOUR::LocaleGuard::~LocaleGuard ()
void void
ARDOUR::setup_fpu () ARDOUR::setup_fpu ()
{ {
#ifdef USE_XMMINTRIN #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
int MXCSR; int MXCSR;
FPU fpu;
/* XXX use real code to determine if the processor supports /* XXX use real code to determine if the processor supports
DenormalsAreZero and FlushToZero DenormalsAreZero and FlushToZero
*/ */
bool has_daz = false; if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
bool can_ftz = true;
if (!can_ftz && !has_daz) {
return; return;
} }
@ -556,25 +528,29 @@ ARDOUR::setup_fpu ()
switch (Config->get_denormal_model()) { switch (Config->get_denormal_model()) {
case DenormalNone: case DenormalNone:
MXCSR &= ~_MM_FLUSH_ZERO_ON; MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
break; break;
case DenormalFTZ: case DenormalFTZ:
MXCSR |= _MM_FLUSH_ZERO_ON; if (fpu.has_flush_to_zero()) {
MXCSR |= _MM_FLUSH_ZERO_ON;
}
break; break;
case DenormalDAZ: case DenormalDAZ:
MXCSR &= ~_MM_FLUSH_ZERO_ON; MXCSR &= ~_MM_FLUSH_ZERO_ON;
if (has_daz) { if (fpu.has_denormals_are_zero()) {
MXCSR |= 0x8000; MXCSR |= 0x8000;
} }
break; break;
case DenormalFTZDAZ: case DenormalFTZDAZ:
if (has_daz) { if (fpu.has_flush_to_zero()) {
MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000; if (fpu.has_denormals_are_zero()) {
} else { MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
MXCSR |= _MM_FLUSH_ZERO_ON; } else {
MXCSR |= _MM_FLUSH_ZERO_ON;
}
} }
break; break;
} }

View file

@ -3278,6 +3278,8 @@ Session::config_changed (const char* parameter_name)
set_slave_source (Config->get_slave_source()); set_slave_source (Config->get_slave_source());
} else if (PARAM_IS ("remote-model")) { } else if (PARAM_IS ("remote-model")) {
set_remote_control_ids (); set_remote_control_ids ();
} else if (PARAM_IS ("denormal-model")) {
setup_fpu ();
} }
set_dirty (); set_dirty ();

View file

@ -27,6 +27,7 @@ controllable.cc
enumwriter.cc enumwriter.cc
dmalloc.cc dmalloc.cc
error.cc error.cc
fpu.cc
id.cc id.cc
mountpoint.cc mountpoint.cc
path.cc path.cc

92
libs/pbd/fpu.cc Normal file
View file

@ -0,0 +1,92 @@
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <stdint.h>
#include <pbd/fpu.h>
#include <pbd/error.h>
#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 ()
{
}

31
libs/pbd/pbd/fpu.h Normal file
View file

@ -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__ */