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('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 ()

View file

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

View file

@ -24,6 +24,7 @@
*/
#include <pbd/pathscanner.h>
#include <pbd/fpu.h>
#include <glibmm/miscutils.h>
@ -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);

View file

@ -37,6 +37,7 @@
#include <pbd/error.h>
#include <pbd/id.h>
#include <pbd/strsplit.h>
#include <pbd/fpu.h>
#include <midi++/port.h>
#include <midi++/port_request.h>
@ -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;
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;
// 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;
}

View file

@ -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 ();

View file

@ -27,6 +27,7 @@ controllable.cc
enumwriter.cc
dmalloc.cc
error.cc
fpu.cc
id.cc
mountpoint.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__ */