summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-10-08 02:17:56 +0200
committerSven Gothel <[email protected]>2011-10-08 02:17:56 +0200
commit727c697f6808caec2fcbcc35d155552590d4f869 (patch)
treed28a78a95bb871f46816481ca84ba0476f39647a /src/jogl/classes/jogamp/opengl
parentda279187e375fdc87ed3a73480c5548602d3454e (diff)
EGL: Fall back to NV_coverage_sample if EGL MSAA/FSAA is n/a
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java11
2 files changed, 16 insertions, 0 deletions
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
index 8a423c6a8..42d911610 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
@@ -38,6 +38,7 @@ public class EGLGLCapabilities extends GLCapabilities {
final int eglcfgid;
final int renderableType;
int nativeVisualID;
+ boolean useNV_coverage_sample;
/** Comparing EGLConfig ID only */
public static class EglCfgIDComparator implements Comparator {
@@ -85,6 +86,7 @@ public class EGLGLCapabilities extends GLCapabilities {
" with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]");
}
this.renderableType = renderableType;
+ this.useNV_coverage_sample = false;
}
public Object cloneMutable() {
@@ -104,6 +106,8 @@ public class EGLGLCapabilities extends GLCapabilities {
final public int getRenderableType() { return renderableType; }
final public void setNativeVisualID(int vid) { nativeVisualID=vid; }
final public int getNativeVisualID() { return nativeVisualID; }
+ final public boolean getUseNV_coverage_sample() { return useNV_coverage_sample; }
+ final public void setUseNV_coverage_sample(boolean v) { useNV_coverage_sample=v; }
public static boolean isCompatible(GLProfile glp, int renderableType) {
if(null == glp) {
@@ -161,6 +165,7 @@ public class EGLGLCapabilities extends GLCapabilities {
sink.append("0x").append(Long.toHexString(eglcfgid)).append(": ");
sink.append("vid 0x").append(Integer.toHexString(nativeVisualID)).append(", ");
super.toString(sink);
+ sink.append(", nv-covrg ").append(getUseNV_coverage_sample());
sink.append(", [");
renderableTypeToString(sink, renderableType);
return sink.append("]");
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 14e67a2c1..5f241a1d0 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
@@ -217,6 +217,17 @@ public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration imple
caps.setSampleBuffers(val.get(0)>0?true:false);
caps.setNumSamples(val.get(0));
}
+ if(!caps.getSampleBuffers()) {
+ // try NV_coverage_sample extension
+ if(EGL.eglGetConfigAttrib(display, config, EGLExt.EGL_COVERAGE_BUFFERS_NV, val)) {
+ if(val.get(0)>0 &&
+ EGL.eglGetConfigAttrib(display, config, EGLExt.EGL_COVERAGE_SAMPLES_NV, val)) {
+ caps.setUseNV_coverage_sample(true);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(val.get(0));
+ }
+ }
+ }
if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_TYPE, val)) {
caps.setBackgroundOpaque(val.get(0) != EGL.EGL_TRANSPARENT_RGB);
}
8'>328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
/**
 * OpenAL cross platform audio library
 * Copyright (C) 2013 by Mike Gorchak
 * This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the
 *  Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 * Or go to http://www.gnu.org/copyleft/lgpl.html
 */

#include "config.h"

#include <math.h>
#include <stdlib.h>

#include "alMain.h"
#include "alFilter.h"
#include "alAuxEffectSlot.h"
#include "alError.h"
#include "alu.h"


/*  The document  "Effects Extension Guide.pdf"  says that low and high  *
 *  frequencies are cutoff frequencies. This is not fully correct, they  *
 *  are corner frequencies for low and high shelf filters. If they were  *
 *  just cutoff frequencies, there would be no need in cutoff frequency  *
 *  gains, which are present.  Documentation for  "Creative Proteus X2"  *
 *  software describes  4-band equalizer functionality in a much better  *
 *  way.  This equalizer seems  to be a predecessor  of  OpenAL  4-band  *
 *  equalizer.  With low and high  shelf filters  we are able to cutoff  *
 *  frequencies below and/or above corner frequencies using attenuation  *
 *  gains (below 1.0) and amplify all low and/or high frequencies using  *
 *  gains above 1.0.                                                     *
 *                                                                       *
 *     Low-shelf       Low Mid Band      High Mid Band     High-shelf    *
 *      corner            center             center          corner      *
 *     frequency        frequency          frequency       frequency     *
 *    50Hz..800Hz     200Hz..3000Hz      1000Hz..8000Hz  4000Hz..16000Hz *
 *                                                                       *
 *          |               |                  |               |         *
 *          |               |                  |               |         *
 *   B -----+            /--+--\            /--+--\            +-----    *
 *   O      |\          |   |   |          |   |   |          /|         *
 *   O      | \        -    |    -        -    |    -        / |         *
 *   S +    |  \      |     |     |      |     |     |      /  |         *
 *   T      |   |    |      |      |    |      |      |    |   |         *
 * ---------+---------------+------------------+---------------+-------- *
 *   C      |   |    |      |      |    |      |      |    |   |         *
 *   U -    |  /      |     |     |      |     |     |      \  |         *
 *   T      | /        -    |    -        -    |    -        \ |         *
 *   O      |/          |   |   |          |   |   |          \|         *
 *   F -----+            \--+--/            \--+--/            +-----    *
 *   F      |               |                  |               |         *
 *          |               |                  |               |         *
 *                                                                       *
 * Gains vary from 0.126 up to 7.943, which means from -18dB attenuation *
 * up to +18dB amplification. Band width varies from 0.01 up to 1.0 in   *
 * octaves for two mid bands.                                            *
 *                                                                       *
 * Implementation is based on the "Cookbook formulae for audio EQ biquad *
 * filter coefficients" by Robert Bristow-Johnson                        *
 * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt                   */


/* The maximum number of sample frames per update. */
#define MAX_UPDATE_SAMPLES 256

typedef struct ALequalizerState {
    DERIVE_FROM_TYPE(ALeffectState);

    /* Effect gains for each channel */
    ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS];

    /* Effect parameters */
    ALfilterState filter[4][MAX_EFFECT_CHANNELS];

    ALfloat SampleBuffer[4][MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES];
} ALequalizerState;

static ALvoid ALequalizerState_Destruct(ALequalizerState *state);
static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *state, ALCdevice *device);
static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props);
static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALequalizerState)

DEFINE_ALEFFECTSTATE_VTABLE(ALequalizerState);


static void ALequalizerState_Construct(ALequalizerState *state)
{
    int it, ft;

    ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
    SET_VTABLE2(ALequalizerState, ALeffectState, state);

    /* Initialize sample history only on filter creation to avoid */
    /* sound clicks if filter settings were changed in runtime.   */
    for(it = 0; it < 4; it++)
    {
        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
            ALfilterState_clear(&state->filter[it][ft]);
    }
}

static ALvoid ALequalizerState_Destruct(ALequalizerState *state)
{
    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}

static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *UNUSED(state), ALCdevice *UNUSED(device))
{
    return AL_TRUE;
}

static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props)
{
    ALfloat frequency = (ALfloat)device->Frequency;
    ALfloat gain, freq_mult;
    ALuint i;

    STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer;
    STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels;
    for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
        ComputeFirstOrderGains(device->FOAOut, IdentityMatrixf.m[i],
                               slot->Params.Gain, state->Gain[i]);

    /* Calculate coefficients for the each type of filter. Note that the shelf
     * filters' gain is for the reference frequency, which is the centerpoint
     * of the transition band.
     */
    gain = maxf(sqrtf(props->Equalizer.LowGain), 0.0625f); /* Limit -24dB */
    freq_mult = props->Equalizer.LowCutoff/frequency;
    ALfilterState_setParams(&state->filter[0][0], ALfilterType_LowShelf,
        gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
    );
    /* Copy the filter coefficients for the other input channels. */
    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
    {
        state->filter[0][i].b0 = state->filter[0][0].b0;
        state->filter[0][i].b1 = state->filter[0][0].b1;
        state->filter[0][i].b2 = state->filter[0][0].b2;
        state->filter[0][i].a1 = state->filter[0][0].a1;
        state->filter[0][i].a2 = state->filter[0][0].a2;
    }

    gain = maxf(props->Equalizer.Mid1Gain, 0.0625f);
    freq_mult = props->Equalizer.Mid1Center/frequency;
    ALfilterState_setParams(&state->filter[1][0], ALfilterType_Peaking,
        gain, freq_mult, calc_rcpQ_from_bandwidth(
            freq_mult, props->Equalizer.Mid1Width
        )
    );
    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
    {
        state->filter[1][i].b0 = state->filter[1][0].b0;
        state->filter[1][i].b1 = state->filter[1][0].b1;
        state->filter[1][i].b2 = state->filter[1][0].b2;
        state->filter[1][i].a1 = state->filter[1][0].a1;
        state->filter[1][i].a2 = state->filter[1][0].a2;
    }

    gain = maxf(props->Equalizer.Mid2Gain, 0.0625f);
    freq_mult = props->Equalizer.Mid2Center/frequency;
    ALfilterState_setParams(&state->filter[2][0], ALfilterType_Peaking,
        gain, freq_mult, calc_rcpQ_from_bandwidth(
            freq_mult, props->Equalizer.Mid2Width
        )
    );
    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
    {
        state->filter[2][i].b0 = state->filter[2][0].b0;
        state->filter[2][i].b1 = state->filter[2][0].b1;
        state->filter[2][i].b2 = state->filter[2][0].b2;
        state->filter[2][i].a1 = state->filter[2][0].a1;
        state->filter[2][i].a2 = state->filter[2][0].a2;
    }

    gain = maxf(sqrtf(props->Equalizer.HighGain), 0.0625f);
    freq_mult = props->Equalizer.HighCutoff/frequency;
    ALfilterState_setParams(&state->filter[3][0], ALfilterType_HighShelf,
        gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
    );
    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
    {
        state->filter[3][i].b0 = state->filter[3][0].b0;
        state->filter[3][i].b1 = state->filter[3][0].b1;
        state->filter[3][i].b2 = state->filter[3][0].b2;
        state->filter[3][i].a1 = state->filter[3][0].a1;
        state->filter[3][i].a2 = state->filter[3][0].a2;
    }
}

static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
{
    ALfloat (*Samples)[MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES] = state->SampleBuffer;
    ALuint it, kt, ft;
    ALuint base;

    for(base = 0;base < SamplesToDo;)
    {
        ALuint td = minu(MAX_UPDATE_SAMPLES, SamplesToDo-base);

        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
            ALfilterState_process(&state->filter[0][ft], Samples[0][ft], &SamplesIn[ft][base], td);
        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
            ALfilterState_process(&state->filter[1][ft], Samples[1][ft], Samples[0][ft], td);
        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
            ALfilterState_process(&state->filter[2][ft], Samples[2][ft], Samples[1][ft], td);
        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
            ALfilterState_process(&state->filter[3][ft], Samples[3][ft], Samples[2][ft], td);

        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
        {
            for(kt = 0;kt < NumChannels;kt++)
            {
                ALfloat gain = state->Gain[ft][kt];
                if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                    continue;