mirror of https://github.com/bsnes-emu/bsnes.git
Update to v083r09 release.
byuu says: Added frequency, latency, resampler selection to the audio settings panel (I really only wanted it there for resampler selection ... having three options matches the driver selection style though, so whatever.) The linear/hermite sampler will double the framerate when running Game Boy games, and sounds the same. Same framerate and sound quality on SNES. But it will cause buzzing in many NES titles. Also re-added the composition { never, fullscreen, always } modes. I think that option is clutter, but it's just impossible to get good audio+video on Windows 7 without it ... Lastly, HQ2x was ported over, but not very well. I just convert source pixels from RGB888 to RGB555, and output pixels in the opposite direction. Need someone good to port the diff() and blend functions over to RGB888 in a way that's not terribly slow.
This commit is contained in:
parent
483f9f8f20
commit
bf78e66027
|
@ -20,6 +20,7 @@ struct Intrinsics {
|
|||
#define COMPILER_VISUALC
|
||||
Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::VisualC; }
|
||||
#else
|
||||
#warning "unable to detect compiler"
|
||||
#define COMPILER_UNKNOWN
|
||||
Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Unknown; }
|
||||
#endif
|
||||
|
@ -37,8 +38,9 @@ struct Intrinsics {
|
|||
#define PLATFORM_WIN
|
||||
Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Windows; }
|
||||
#else
|
||||
#warning "unable to detect platform"
|
||||
#define PLATFORM_UNKNOWN
|
||||
|
||||
Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Unknown; }
|
||||
#endif
|
||||
|
||||
/* Endian detection */
|
||||
|
@ -52,9 +54,10 @@ struct Intrinsics {
|
|||
#define ARCH_MSB
|
||||
Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::MSB; }
|
||||
#else
|
||||
#warning "unable to detect endian"
|
||||
#define ENDIAN_UNKNOWN
|
||||
#define ARCH_UNKNOWN
|
||||
Intrinsics::Endian Intrinsics::endia() { return Intrinsics::Endian::Unknown; }
|
||||
Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::Unknown; }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,13 @@ namespace nall {
|
|||
buffersize = newsize;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
bool append(const T& data, Args&&... args) {
|
||||
bool result = append(data);
|
||||
append(std::forward<Args>(args)...);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool append(const T data) {
|
||||
for(unsigned index = 0; index < buffersize; index++) {
|
||||
if(pool[index] == &data) return false;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <snes/snes.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#include <nall/compositor.hpp>
|
||||
#include <nall/config.hpp>
|
||||
#include <nall/directory.hpp>
|
||||
#include <nall/dsp.hpp>
|
||||
|
@ -32,6 +33,7 @@ struct Application {
|
|||
bool quit;
|
||||
bool pause;
|
||||
bool autopause;
|
||||
bool compositionEnable;
|
||||
|
||||
string basepath;
|
||||
string userpath;
|
||||
|
|
|
@ -19,12 +19,14 @@ Config::Config() {
|
|||
attach(video.fullScreenMode = 0, "Video::FullScreenMode");
|
||||
|
||||
attach(video.startFullScreen = false, "Video::StartFullScreen");
|
||||
attach(video.compositionMode = 0, "Video::CompositionMode");
|
||||
|
||||
attach(audio.driver = "", "Audio::Driver");
|
||||
attach(audio.synchronize = true, "Audio::Synchronize");
|
||||
attach(audio.mute = false, "Audio::Mute");
|
||||
attach(audio.volume = 100, "Audio::Volume");
|
||||
attach(audio.latency = 60, "Audio::Latency");
|
||||
attach(audio.resampler = "sinc", "Audio::Resampler");
|
||||
|
||||
attach(audio.frequency = 48000, "Audio::Frequency::Native");
|
||||
attach(audio.frequencyNES = 1789772, "Audio::Frequency::NES");
|
||||
|
|
|
@ -15,6 +15,7 @@ struct Config : public configuration {
|
|||
unsigned gamma;
|
||||
|
||||
unsigned fullScreenMode;
|
||||
unsigned compositionMode;
|
||||
|
||||
bool startFullScreen;
|
||||
} video;
|
||||
|
@ -25,6 +26,7 @@ struct Config : public configuration {
|
|||
bool mute;
|
||||
unsigned volume;
|
||||
unsigned latency;
|
||||
string resampler;
|
||||
|
||||
unsigned frequency;
|
||||
unsigned frequencyNES;
|
||||
|
|
|
@ -35,9 +35,7 @@ GameBoyController::GameBoyController() {
|
|||
select.mapping = "KB0::Apostrophe";
|
||||
start.mapping = "KB0::Return";
|
||||
|
||||
append(up); append(down); append(left); append(right);
|
||||
append(b); append(a); append(select); append(start);
|
||||
append(bTurbo); append(aTurbo);
|
||||
append(up, down, left, right, b, a, select, start, bTurbo, aTurbo);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -35,9 +35,7 @@ NesGamepad::NesGamepad() {
|
|||
select.mapping = "KB0::Apostrophe";
|
||||
start.mapping = "KB0::Return";
|
||||
|
||||
append(up); append(down); append(left); append(right);
|
||||
append(b); append(a); append(select); append(start);
|
||||
append(bTurbo); append(aTurbo);
|
||||
append(up, down, left, right, b,a, select, start, bTurbo, aTurbo);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -58,6 +56,5 @@ NesPort2Input::NesPort2Input() {
|
|||
|
||||
NesInput::NesInput() {
|
||||
name = "NES";
|
||||
append(port1);
|
||||
append(port2);
|
||||
append(port1, port1);
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ int16_t SnesGamepad::poll(unsigned n) {
|
|||
case SNES::Input::JoypadID::A: return a.poll() | aTurbo.poll();
|
||||
case SNES::Input::JoypadID::Y: return y.poll() | yTurbo.poll();
|
||||
case SNES::Input::JoypadID::X: return x.poll() | xTurbo.poll();
|
||||
case SNES::Input::JoypadID::L: return l.poll();
|
||||
case SNES::Input::JoypadID::R: return r.poll();
|
||||
case SNES::Input::JoypadID::L: return l.poll() | lTurbo.poll();
|
||||
case SNES::Input::JoypadID::R: return r.poll() | rTurbo.poll();
|
||||
case SNES::Input::JoypadID::Select: return select.poll();
|
||||
case SNES::Input::JoypadID::Start: return start.poll();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ SnesGamepad::SnesGamepad(const string &name, bool defaultBindings) {
|
|||
b.name = "B", a.name = "A", y.name = "Y", x.name = "X";
|
||||
l.name = "L", r.name = "R", select.name = "Select", start.name = "Start";
|
||||
bTurbo.name = "Turbo B", aTurbo.name = "Turbo A", yTurbo.name = "Turbo Y", xTurbo.name = "Turbo X";
|
||||
lTurbo.name = "Turbo L", rTurbo.name = "Turbo R";
|
||||
|
||||
if(defaultBindings) {
|
||||
up.mapping = "KB0::Up";
|
||||
|
@ -39,10 +40,8 @@ SnesGamepad::SnesGamepad(const string &name, bool defaultBindings) {
|
|||
start.mapping = "KB0::Return";
|
||||
}
|
||||
|
||||
append(up); append(down); append(left); append(right);
|
||||
append(b); append(a); append(y); append(x);
|
||||
append(l); append(r); append(select); append(start);
|
||||
append(bTurbo); append(aTurbo); append(yTurbo); append(xTurbo);
|
||||
append(up, down, left, right, b, a, y, x, l, r, select, start);
|
||||
append(bTurbo, aTurbo, yTurbo, xTurbo, lTurbo, rTurbo);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -70,8 +69,7 @@ SnesMouse::SnesMouse(const string &name, bool defaultBindings) {
|
|||
right.mapping = "MS0::Button2";
|
||||
}
|
||||
|
||||
append(xaxis); append(yaxis);
|
||||
append(left); append(right);
|
||||
append(xaxis, yaxis, left, right);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -103,8 +101,7 @@ SnesSuperScope::SnesSuperScope(const string &name, bool defaultBindings) {
|
|||
pause.mapping = "KB0::P";
|
||||
}
|
||||
|
||||
append(xaxis); append(yaxis);
|
||||
append(trigger); append(cursor); append(turbo); append(pause);
|
||||
append(xaxis, yaxis, trigger, cursor, turbo, pause);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -132,8 +129,7 @@ SnesJustifier::SnesJustifier(const string &name, bool defaultBindings) {
|
|||
start.mapping = "MS0::Button2";
|
||||
}
|
||||
|
||||
append(xaxis), append(yaxis);
|
||||
append(trigger), append(start);
|
||||
append(xaxis, yaxis, trigger, start);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -184,6 +180,5 @@ justifier2("Justifier - Port 2", false)
|
|||
|
||||
SnesInput::SnesInput() {
|
||||
name = "SNES";
|
||||
append(port1);
|
||||
append(port2);
|
||||
append(port1, port2);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ struct SnesGamepad : TertiaryInput {
|
|||
DigitalInput b, a, y, x;
|
||||
DigitalInput l, r, select, start;
|
||||
TurboInput bTurbo, aTurbo, yTurbo, xTurbo;
|
||||
TurboInput lTurbo, rTurbo;
|
||||
|
||||
int16_t poll(unsigned n);
|
||||
SnesGamepad(const string &name, bool defaultBindings);
|
||||
|
|
|
@ -44,7 +44,15 @@ void Interface::setController(unsigned port, unsigned device) {
|
|||
}
|
||||
|
||||
void Interface::updateDSP() {
|
||||
audio.set(Audio::Frequency, config->audio.frequency);
|
||||
audio.set(Audio::Latency, config->audio.latency);
|
||||
|
||||
if(config->audio.resampler == "linear" ) dspaudio.setResampler(DSP::ResampleEngine::Linear);
|
||||
if(config->audio.resampler == "hermite") dspaudio.setResampler(DSP::ResampleEngine::Hermite);
|
||||
if(config->audio.resampler == "sinc" ) dspaudio.setResampler(DSP::ResampleEngine::Sinc);
|
||||
dspaudio.setResamplerFrequency(config->audio.frequency);
|
||||
dspaudio.setVolume(config->audio.mute == false ? (double)config->audio.volume / 100.0 : 0.0);
|
||||
|
||||
switch(mode()) {
|
||||
case Mode::NES: return dspaudio.setFrequency(config->audio.frequencyNES);
|
||||
case Mode::SNES: return dspaudio.setFrequency(config->audio.frequencySNES);
|
||||
|
|
|
@ -27,7 +27,7 @@ void Application::run() {
|
|||
}
|
||||
|
||||
Application::Application(int argc, char **argv) {
|
||||
title = "bsnes v083.08";
|
||||
title = "bsnes v083.09";
|
||||
|
||||
application = this;
|
||||
quit = false;
|
||||
|
@ -56,6 +56,9 @@ Application::Application(int argc, char **argv) {
|
|||
boldFont = { fontFamily, "8, Bold" };
|
||||
titleFont = { fontFamily, "16, Bold" };
|
||||
|
||||
compositionEnable = compositor::enabled();
|
||||
if(config->video.compositionMode == 2) compositor::enable(false);
|
||||
|
||||
windowManager = new WindowManager;
|
||||
mainWindow = new MainWindow;
|
||||
fileBrowser = new FileBrowser;
|
||||
|
@ -104,6 +107,7 @@ Application::Application(int argc, char **argv) {
|
|||
|
||||
interface->unloadCartridge();
|
||||
windowManager->saveGeometry();
|
||||
if(compositionEnable) compositor::enable(true);
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
|
|
@ -16,7 +16,7 @@ AdvancedSettings::AdvancedSettings() {
|
|||
RadioBox::group(focusPolicy[0], focusPolicy[1], focusPolicy[2]);
|
||||
focusPolicy[config->input.focusPolicy].setChecked();
|
||||
aboutLabel.setFont(application->boldFont);
|
||||
aboutLabel.setText("bsnes author: byuu license: GPLv3 website: http://byuu.org/");
|
||||
aboutLabel.setText("bsnes author: byuu license: GPLv3 website: byuu.org");
|
||||
|
||||
lstring list;
|
||||
|
||||
|
|
|
@ -23,6 +23,33 @@ void AudioSlider::setPosition(unsigned position) {
|
|||
AudioSettings::AudioSettings() {
|
||||
title.setFont(application->titleFont);
|
||||
title.setText("Audio Settings");
|
||||
|
||||
outputLabel.setFont(application->boldFont);
|
||||
outputLabel.setText("Output settings:");
|
||||
|
||||
frequencyLabel.setText("Frequency:");
|
||||
frequencySelection.append("32000hz");
|
||||
frequencySelection.append("44100hz");
|
||||
frequencySelection.append("48000hz");
|
||||
frequencySelection.append("96000hz");
|
||||
|
||||
latencyLabel.setText("Latency:");
|
||||
latencySelection.append( "40ms");
|
||||
latencySelection.append( "60ms");
|
||||
latencySelection.append( "80ms");
|
||||
latencySelection.append("100ms");
|
||||
latencySelection.append("120ms");
|
||||
|
||||
resamplerLabel.setText("Resampler:");
|
||||
resamplerSelection.append("Linear");
|
||||
resamplerSelection.append("Hermite");
|
||||
resamplerSelection.append("Sinc");
|
||||
|
||||
volume.name.setText("Volume:");
|
||||
volume.slider.setLength(201);
|
||||
volume.base = 100;
|
||||
volume.step = 1;
|
||||
|
||||
frequencyAdjustmentLabel.setFont(application->boldFont);
|
||||
frequencyAdjustmentLabel.setText("Frequency: (lower to reduce audio crackling; raise to reduce video tearing)");
|
||||
|
||||
|
@ -41,39 +68,79 @@ AudioSettings::AudioSettings() {
|
|||
gameBoy.base = 4194304;
|
||||
gameBoy.step = 131;
|
||||
|
||||
outputAdjustmentLabel.setFont(application->boldFont);
|
||||
outputAdjustmentLabel.setText("Output:");
|
||||
|
||||
volume.name.setText("Volume:");
|
||||
volume.slider.setLength(201);
|
||||
volume.base = 100;
|
||||
volume.step = 1;
|
||||
|
||||
append(title, ~0, 0, 5);
|
||||
append(outputLabel, ~0, 0);
|
||||
append(outputLayout, ~0, 0, 5);
|
||||
outputLayout.append(frequencyLabel, 0, 0, 5);
|
||||
outputLayout.append(frequencySelection, ~0, 0, 5);
|
||||
outputLayout.append(latencyLabel, 0, 0, 5);
|
||||
outputLayout.append(latencySelection, ~0, 0, 5);
|
||||
outputLayout.append(resamplerLabel, 0, 0, 5);
|
||||
outputLayout.append(resamplerSelection, ~0, 0);
|
||||
append(volume, ~0, 0, 5);
|
||||
append(frequencyAdjustmentLabel, ~0, 0);
|
||||
append(nes, ~0, 0);
|
||||
append(snes, ~0, 0);
|
||||
append(gameBoy, ~0, 0, 5);
|
||||
append(outputAdjustmentLabel, ~0, 0);
|
||||
append(volume, ~0, 0);
|
||||
append(gameBoy, ~0, 0);
|
||||
|
||||
frequencySelection.setSelection(
|
||||
config->audio.frequency == 32000 ? 0 :
|
||||
config->audio.frequency == 44100 ? 1 :
|
||||
config->audio.frequency == 48000 ? 2 :
|
||||
config->audio.frequency == 96000 ? 3 : 0
|
||||
);
|
||||
|
||||
latencySelection.setSelection(
|
||||
config->audio.latency == 40 ? 0 :
|
||||
config->audio.latency == 60 ? 1 :
|
||||
config->audio.latency == 80 ? 2 :
|
||||
config->audio.latency == 100 ? 3 :
|
||||
config->audio.latency == 120 ? 4 : 0
|
||||
);
|
||||
|
||||
resamplerSelection.setSelection(
|
||||
config->audio.resampler == "linear" ? 0 :
|
||||
config->audio.resampler == "hermite" ? 1 :
|
||||
config->audio.resampler == "sinc" ? 2 : 0
|
||||
);
|
||||
|
||||
volume.setPosition(config->audio.volume);
|
||||
|
||||
nes.setPosition(config->audio.frequencyNES);
|
||||
snes.setPosition(config->audio.frequencySNES);
|
||||
gameBoy.setPosition(config->audio.frequencyGameBoy);
|
||||
volume.setPosition(config->audio.volume);
|
||||
|
||||
nes.slider.onChange = snes.slider.onChange = gameBoy.slider.onChange =
|
||||
volume.slider.onChange =
|
||||
frequencySelection.onChange = latencySelection.onChange = resamplerSelection.onChange =
|
||||
volume.slider.onChange = nes.slider.onChange = snes.slider.onChange = gameBoy.slider.onChange =
|
||||
{ &AudioSettings::synchronize, this };
|
||||
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void AudioSettings::synchronize() {
|
||||
config->audio.frequency =
|
||||
frequencySelection.selection() == 0 ? 32000 :
|
||||
frequencySelection.selection() == 1 ? 44100 :
|
||||
frequencySelection.selection() == 2 ? 48000 :
|
||||
frequencySelection.selection() == 3 ? 96000 : 48000;
|
||||
|
||||
config->audio.latency =
|
||||
latencySelection.selection() == 0 ? 40 :
|
||||
latencySelection.selection() == 1 ? 60 :
|
||||
latencySelection.selection() == 2 ? 80 :
|
||||
latencySelection.selection() == 3 ? 100 :
|
||||
latencySelection.selection() == 4 ? 120 : 60;
|
||||
|
||||
config->audio.resampler =
|
||||
resamplerSelection.selection() == 0 ? "linear" :
|
||||
resamplerSelection.selection() == 1 ? "hermite" :
|
||||
resamplerSelection.selection() == 2 ? "sinc" : "sinc";
|
||||
|
||||
config->audio.volume = volume.position();
|
||||
|
||||
config->audio.frequencyNES = nes.position();
|
||||
config->audio.frequencySNES = snes.position();
|
||||
config->audio.frequencyGameBoy = gameBoy.position();
|
||||
config->audio.volume = volume.position();
|
||||
|
||||
nes.value.setText({ nes.position(), "hz" });
|
||||
snes.value.setText({ snes.position(), "hz" });
|
||||
|
|
|
@ -13,12 +13,19 @@ struct AudioSlider : HorizontalLayout {
|
|||
|
||||
struct AudioSettings : SettingsLayout {
|
||||
Label title;
|
||||
Label outputLabel;
|
||||
HorizontalLayout outputLayout;
|
||||
Label frequencyLabel;
|
||||
ComboBox frequencySelection;
|
||||
Label latencyLabel;
|
||||
ComboBox latencySelection;
|
||||
Label resamplerLabel;
|
||||
ComboBox resamplerSelection;
|
||||
AudioSlider volume;
|
||||
Label frequencyAdjustmentLabel;
|
||||
AudioSlider nes;
|
||||
AudioSlider snes;
|
||||
AudioSlider gameBoy;
|
||||
Label outputAdjustmentLabel;
|
||||
AudioSlider volume;
|
||||
|
||||
void synchronize();
|
||||
AudioSettings();
|
||||
|
|
|
@ -29,6 +29,12 @@ VideoSettings::VideoSettings() {
|
|||
fullScreen[1].setText("Scale");
|
||||
fullScreen[2].setText("Stretch");
|
||||
RadioBox::group(fullScreen[0], fullScreen[1], fullScreen[2]);
|
||||
compositorLabel.setText("Disable window compositor:");
|
||||
compositorLabel.setFont(application->boldFont);
|
||||
compositor[0].setText("Never");
|
||||
compositor[1].setText("Fullscreen");
|
||||
compositor[2].setText("Always");
|
||||
RadioBox::group(compositor[0], compositor[1], compositor[2]);
|
||||
|
||||
append(title, ~0, 0, 5);
|
||||
append(colorAdjustment, ~0, 0);
|
||||
|
@ -39,10 +45,15 @@ VideoSettings::VideoSettings() {
|
|||
append(overscanHorizontal, ~0, 0);
|
||||
append(overscanVertical, ~0, 0, 5);
|
||||
append(fullScreenMode, ~0, 0);
|
||||
append(fullScreenLayout, ~0, 0);
|
||||
append(fullScreenLayout, ~0, 0, 5);
|
||||
fullScreenLayout.append(fullScreen[0], ~0, 0, 5);
|
||||
fullScreenLayout.append(fullScreen[1], ~0, 0, 5);
|
||||
fullScreenLayout.append(fullScreen[2], ~0, 0);
|
||||
append(compositorLabel, ~0, 0);
|
||||
append(compositorLayout, ~0, 0);
|
||||
compositorLayout.append(compositor[0], ~0, 0, 5);
|
||||
compositorLayout.append(compositor[1], ~0, 0, 5);
|
||||
compositorLayout.append(compositor[2], ~0, 0);
|
||||
|
||||
brightness.slider.setPosition(config->video.brightness);
|
||||
contrast.slider.setPosition(config->video.contrast);
|
||||
|
@ -50,13 +61,32 @@ VideoSettings::VideoSettings() {
|
|||
overscanHorizontal.slider.setPosition(config->video.maskOverscanHorizontal);
|
||||
overscanVertical.slider.setPosition(config->video.maskOverscanVertical);
|
||||
fullScreen[config->video.fullScreenMode].setChecked();
|
||||
compositor[config->video.compositionMode].setChecked();
|
||||
|
||||
synchronize();
|
||||
|
||||
brightness.slider.onChange = contrast.slider.onChange = gamma.slider.onChange =
|
||||
overscanHorizontal.slider.onChange = overscanVertical.slider.onChange =
|
||||
fullScreen[0].onTick = fullScreen[1].onTick = fullScreen[2].onTick =
|
||||
{ &VideoSettings::synchronize, this };
|
||||
|
||||
fullScreen[0].onTick = [&] { config->video.fullScreenMode = 0; };
|
||||
fullScreen[1].onTick = [&] { config->video.fullScreenMode = 1; };
|
||||
fullScreen[2].onTick = [&] { config->video.fullScreenMode = 2; };
|
||||
|
||||
compositor[0].onTick = [&] {
|
||||
config->video.compositionMode = 0;
|
||||
compositor::enable(application->compositionEnable);
|
||||
};
|
||||
|
||||
compositor[1].onTick = [&] {
|
||||
config->video.compositionMode = 1;
|
||||
compositor::enable(application->compositionEnable && mainWindow->fullScreen() == false);
|
||||
};
|
||||
|
||||
compositor[2].onTick = [&] {
|
||||
config->video.compositionMode = 2;
|
||||
compositor::enable(false);
|
||||
};
|
||||
}
|
||||
|
||||
void VideoSettings::synchronize() {
|
||||
|
@ -65,9 +95,9 @@ void VideoSettings::synchronize() {
|
|||
config->video.gamma = gamma.slider.position();
|
||||
config->video.maskOverscanHorizontal = overscanHorizontal.slider.position();
|
||||
config->video.maskOverscanVertical = overscanVertical.slider.position();
|
||||
if(fullScreen[0].checked()) config->video.fullScreenMode = 0;
|
||||
if(fullScreen[1].checked()) config->video.fullScreenMode = 1;
|
||||
if(fullScreen[2].checked()) config->video.fullScreenMode = 2;
|
||||
if(fullScreen[0].checked()) { config->video.fullScreenMode = 0; }
|
||||
if(fullScreen[1].checked()) { config->video.fullScreenMode = 1; }
|
||||
if(fullScreen[2].checked()) { config->video.fullScreenMode = 2; }
|
||||
|
||||
brightness.value.setText({ config->video.brightness, "%" });
|
||||
contrast.value.setText({ config->video.contrast, "%" });
|
||||
|
|
|
@ -18,6 +18,9 @@ struct VideoSettings : SettingsLayout {
|
|||
Label fullScreenMode;
|
||||
HorizontalLayout fullScreenLayout;
|
||||
RadioBox fullScreen[3];
|
||||
Label compositorLabel;
|
||||
HorizontalLayout compositorLayout;
|
||||
RadioBox compositor[3];
|
||||
|
||||
void synchronize();
|
||||
VideoSettings();
|
||||
|
|
|
@ -109,6 +109,11 @@ void Utility::toggleFullScreen() {
|
|||
}
|
||||
|
||||
resizeMainWindow();
|
||||
if(application->compositionEnable) {
|
||||
if(config->video.compositionMode == 1) {
|
||||
compositor::enable(mainWindow->fullScreen() == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Utility::bindVideoFilter() {
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -34,6 +34,15 @@ const uint8_t hqTable[256] = {
|
|||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 1, 12, 5, 3, 1, 14,
|
||||
};
|
||||
|
||||
static uint16_t rgb555(uint32_t C) {
|
||||
return ((C >> 9) & 0x7c00) + ((C >> 6) & 0x03e0) + ((C >> 3) & 0x001f);
|
||||
}
|
||||
|
||||
static uint32_t rgb888(uint16_t C) {
|
||||
return ((C & 0x7c00) << 9) + ((C & 0x03e0) << 6) + ((C & 0x001f) << 3)
|
||||
+ ((C & 0x7000) << 4) + ((C & 0x0380) << 1) + ((C & 0x001c) >> 2);
|
||||
}
|
||||
|
||||
static void initialize() {
|
||||
static bool initialized = false;
|
||||
if(initialized == true) return;
|
||||
|
@ -42,16 +51,12 @@ static void initialize() {
|
|||
yuvTable = new uint32_t[32768];
|
||||
|
||||
for(unsigned i = 0; i < 32768; i++) {
|
||||
uint8_t R = (i >> 0) & 31;
|
||||
uint8_t G = (i >> 5) & 31;
|
||||
uint8_t B = (i >> 10) & 31;
|
||||
uint32_t C = rgb888(i);
|
||||
|
||||
//bgr555->bgr888
|
||||
double r = (R << 3) | (R >> 2);
|
||||
double g = (G << 3) | (G >> 2);
|
||||
double b = (B << 3) | (B >> 2);
|
||||
double r = (uint8_t)(C >> 16);
|
||||
double g = (uint8_t)(C >> 8);
|
||||
double b = (uint8_t)(C >> 0);
|
||||
|
||||
//bgr888->yuv
|
||||
double y = (r + g + b) * (0.25f * (63.5f / 48.0f));
|
||||
double u = ((r - b) * 0.25f + 128.0f) * (7.5f / 7.0f);
|
||||
double v = ((g * 2.0f - r - b) * 0.125f + 128.0f) * (7.5f / 6.0f);
|
||||
|
@ -147,18 +152,18 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
initialize();
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 2;
|
||||
uint16_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 2;
|
||||
uint32_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
|
||||
int prevline = (y == 0 ? 0 : inputPitch);
|
||||
int nextline = (y == height - 1 ? 0 : inputPitch);
|
||||
|
@ -168,15 +173,15 @@ dllexport void filter_render(
|
|||
*out1++ = 0; *out1++ = 0;
|
||||
|
||||
for(unsigned x = 1; x < width - 1; x++) {
|
||||
uint16_t A = *(in - prevline - 1);
|
||||
uint16_t B = *(in - prevline + 0);
|
||||
uint16_t C = *(in - prevline + 1);
|
||||
uint16_t D = *(in - 1);
|
||||
uint16_t E = *(in + 0);
|
||||
uint16_t F = *(in + 1);
|
||||
uint16_t G = *(in + nextline - 1);
|
||||
uint16_t H = *(in + nextline + 0);
|
||||
uint16_t I = *(in + nextline + 1);
|
||||
uint16_t A = rgb555(*(in - prevline - 1));
|
||||
uint16_t B = rgb555(*(in - prevline + 0));
|
||||
uint16_t C = rgb555(*(in - prevline + 1));
|
||||
uint16_t D = rgb555(*(in - 1));
|
||||
uint16_t E = rgb555(*(in + 0));
|
||||
uint16_t F = rgb555(*(in + 1));
|
||||
uint16_t G = rgb555(*(in + nextline - 1));
|
||||
uint16_t H = rgb555(*(in + nextline + 0));
|
||||
uint16_t I = rgb555(*(in + nextline + 1));
|
||||
uint32_t e = yuvTable[E] + diff_offset;
|
||||
|
||||
uint8_t pattern;
|
||||
|
@ -189,10 +194,10 @@ dllexport void filter_render(
|
|||
pattern |= diff(e, H) << 6;
|
||||
pattern |= diff(e, I) << 7;
|
||||
|
||||
*(out0 + 0) = blend(hqTable[pattern], E, A, B, D, F, H); pattern = rotate[pattern];
|
||||
*(out0 + 1) = blend(hqTable[pattern], E, C, F, B, H, D); pattern = rotate[pattern];
|
||||
*(out1 + 1) = blend(hqTable[pattern], E, I, H, F, D, B); pattern = rotate[pattern];
|
||||
*(out1 + 0) = blend(hqTable[pattern], E, G, D, H, B, F);
|
||||
*(out0 + 0) = rgb888(blend(hqTable[pattern], E, A, B, D, F, H)); pattern = rotate[pattern];
|
||||
*(out0 + 1) = rgb888(blend(hqTable[pattern], E, C, F, B, H, D)); pattern = rotate[pattern];
|
||||
*(out1 + 1) = rgb888(blend(hqTable[pattern], E, I, H, F, D, B)); pattern = rotate[pattern];
|
||||
*(out1 + 0) = rgb888(blend(hqTable[pattern], E, G, D, H, B, F));
|
||||
|
||||
in++;
|
||||
out0 += 2;
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
|
@ -13,33 +13,33 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 2;
|
||||
uint16_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 2;
|
||||
uint32_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
|
||||
int prevline = (y == 0 ? 0 : inputPitch);
|
||||
int nextline = (y == height - 1 ? 0 : inputPitch);
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t A = *(input - prevline);
|
||||
uint16_t B = (x > 0) ? *(input - 1) : *input;
|
||||
uint16_t C = *input;
|
||||
uint16_t D = (x < width - 1) ? *(input + 1) : *input;
|
||||
uint16_t E = *(input++ + nextline);
|
||||
uint32_t A = *(in - prevline);
|
||||
uint32_t B = (x > 0) ? *(in - 1) : *in;
|
||||
uint32_t C = *in;
|
||||
uint32_t D = (x < width - 1) ? *(in + 1) : *in;
|
||||
uint32_t E = *(in++ + nextline);
|
||||
|
||||
if(A != E && B != D) {
|
||||
*out0++ = (A == B ? C + A - ((C ^ A) & 0x0421) >> 1 : C);
|
||||
*out0++ = (A == D ? C + A - ((C ^ A) & 0x0421) >> 1 : C);
|
||||
*out1++ = (E == B ? C + E - ((C ^ E) & 0x0421) >> 1 : C);
|
||||
*out1++ = (E == D ? C + E - ((C ^ E) & 0x0421) >> 1 : C);
|
||||
*out0++ = (A == B ? C + A - ((C ^ A) & 0x010101) >> 1 : C);
|
||||
*out0++ = (A == D ? C + A - ((C ^ A) & 0x010101) >> 1 : C);
|
||||
*out1++ = (E == B ? C + E - ((C ^ E) & 0x010101) >> 1 : C);
|
||||
*out1++ = (E == D ? C + E - ((C ^ E) & 0x010101) >> 1 : C);
|
||||
} else {
|
||||
*out0++ = C;
|
||||
*out0++ = C;
|
||||
|
|
|
@ -16,7 +16,6 @@ objects += out/Scanline-Light.filter
|
|||
objects += out/Scale2x.filter
|
||||
objects += out/LQ2x.filter
|
||||
objects += out/HQ2x.filter
|
||||
objects += out/Overscan.filter
|
||||
objects += out/Phosphor3x.filter
|
||||
|
||||
compile = $(cpp) $(link) $(flags) -o $@ -shared $<
|
||||
|
@ -31,7 +30,6 @@ out/Scanline-Light.filter: Scanline/Scanline-Light.cpp Scanline/*
|
|||
out/Scale2x.filter: Scale2x/Scale2x.cpp Scale2x/*
|
||||
out/LQ2x.filter: LQ2x/LQ2x.cpp LQ2x/*
|
||||
out/HQ2x.filter: HQ2x/HQ2x.cpp HQ2x/*
|
||||
out/Overscan.filter: Overscan/Overscan.cpp Overscan/*
|
||||
out/Phosphor3x.filter: Phosphor3x/Phosphor3x.cpp Phosphor3x/*
|
||||
|
||||
build: $(objects)
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
#include <nall/platform.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
using namespace nall;
|
||||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out = output + y * outputPitch;
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t pixel = *in++;
|
||||
if(x < 8 || x >= width - 8 || y < 8 || y >= height - 8) pixel = 0;
|
||||
*out++ = pixel;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
|
@ -13,33 +13,45 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 3;
|
||||
uint16_t *out1 = output + y * outputPitch * 3 + outputPitch;
|
||||
uint16_t *out2 = output + y * outputPitch * 3 + outputPitch + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 3;
|
||||
uint32_t *out1 = output + y * outputPitch * 3 + outputPitch;
|
||||
uint32_t *out2 = output + y * outputPitch * 3 + outputPitch + outputPitch;
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t full = *in++, half = (full >> 1) & 0x3def;
|
||||
uint32_t A = (x == 0 ? 0 : *(in - 1));
|
||||
uint32_t B = *in;
|
||||
uint32_t C = (x == width - 1 ? 0 : *(in + 1));
|
||||
|
||||
*out0++ = (full & 0x7c00);
|
||||
*out1++ = (full & 0x7c00);
|
||||
*out2++ = (half & 0x7c00);
|
||||
uint8_t Ar = A >> 16, Ag = A >> 8, Ab = A >> 0;
|
||||
uint8_t Br = B >> 16, Bg = B >> 8, Bb = B >> 0;
|
||||
uint8_t Cr = C >> 16, Cg = C >> 8, Cb = C >> 0;
|
||||
|
||||
*out0++ = (full & 0x03e0);
|
||||
*out1++ = (full & 0x03e0);
|
||||
*out2++ = (half & 0x03e0);
|
||||
A = ((Br >> 0) << 16) + ((Bg >> 1) << 8) + ((Ab >> 1) << 0);
|
||||
B = ((Br >> 1) << 16) + ((Bg >> 0) << 8) + ((Bb >> 1) << 0);
|
||||
C = ((Cr >> 1) << 16) + ((Bg >> 1) << 8) + ((Bb >> 0) << 0);
|
||||
|
||||
*out0++ = (full & 0x001f);
|
||||
*out1++ = (full & 0x001f);
|
||||
*out2++ = (half & 0x001f);
|
||||
in++;
|
||||
|
||||
*out0++ = A;
|
||||
*out1++ = A;
|
||||
*out2++ = (A & 0xf8f8f8) >> 1;
|
||||
|
||||
*out0++ = B;
|
||||
*out1++ = B;
|
||||
*out2++ = (B & 0xf8f8f8) >> 1;
|
||||
|
||||
*out0++ = C;
|
||||
*out1++ = C;
|
||||
*out2++ = (C & 0xf8f8f8) >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
|
@ -13,20 +13,20 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 2;
|
||||
uint16_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 2;
|
||||
uint32_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t pixel = *in++;
|
||||
uint32_t pixel = *in++;
|
||||
*out0++ = pixel;
|
||||
*out0++ = pixel;
|
||||
*out1++ = pixel;
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
|
@ -13,27 +13,27 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 2;
|
||||
uint16_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 2;
|
||||
uint32_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
|
||||
int prevline = (y == 0 ? 0 : inputPitch);
|
||||
int nextline = (y == height - 1 ? 0 : inputPitch);
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t A = *(input - prevline);
|
||||
uint16_t B = (x > 0) ? *(input - 1) : *input;
|
||||
uint16_t C = *input;
|
||||
uint16_t D = (x < width - 1) ? *(input + 1) : *input;
|
||||
uint16_t E = *(input++ + nextline);
|
||||
uint32_t A = *(in - prevline);
|
||||
uint32_t B = (x > 0) ? *(in - 1) : *in;
|
||||
uint32_t C = *in;
|
||||
uint32_t D = (x < width - 1) ? *(in + 1) : *in;
|
||||
uint32_t E = *(in++ + nextline);
|
||||
|
||||
if(A != E && B != D) {
|
||||
*out0++ = (A == B ? A : C);
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
|
@ -12,17 +12,17 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 2;
|
||||
uint16_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 2;
|
||||
uint32_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
*out0++ = *in++;
|
||||
|
|
|
@ -4,7 +4,7 @@ using namespace nall;
|
|||
|
||||
extern "C" {
|
||||
void filter_size(unsigned&, unsigned&);
|
||||
void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
dllexport void filter_size(unsigned &width, unsigned &height) {
|
||||
|
@ -12,21 +12,21 @@ dllexport void filter_size(unsigned &width, unsigned &height) {
|
|||
}
|
||||
|
||||
dllexport void filter_render(
|
||||
uint16_t *output, unsigned outputPitch,
|
||||
const uint16_t *input, unsigned inputPitch,
|
||||
uint32_t *output, unsigned outputPitch,
|
||||
const uint32_t *input, unsigned inputPitch,
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
outputPitch >>= 1, inputPitch >>= 1;
|
||||
outputPitch >>= 2, inputPitch >>= 2;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * inputPitch;
|
||||
uint16_t *out0 = output + y * outputPitch * 2;
|
||||
uint16_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
const uint32_t *in = input + y * inputPitch;
|
||||
uint32_t *out0 = output + y * outputPitch * 2;
|
||||
uint32_t *out1 = output + y * outputPitch * 2 + outputPitch;
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
*out0++ = *in;
|
||||
*out1++ = (*in++ & 0x7bde) >> 1;
|
||||
*out1++ = (*in++ & 0xf8f8f8) >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue