From c5e4de9542dfcdedc3021cc3e6dedae3278c8736 Mon Sep 17 00:00:00 2001 From: Sour Date: Thu, 7 Feb 2019 19:45:17 -0500 Subject: [PATCH] Video: Precalculate brightness/etc for the palette instead of manually applying it to each pixel --- Core/DefaultVideoFilter.cpp | 68 +++++++++++++++++++------------------ Core/DefaultVideoFilter.h | 3 +- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/Core/DefaultVideoFilter.cpp b/Core/DefaultVideoFilter.cpp index 174ae6a4..aa173024 100644 --- a/Core/DefaultVideoFilter.cpp +++ b/Core/DefaultVideoFilter.cpp @@ -50,22 +50,48 @@ void DefaultVideoFilter::OnBeforeApplyFilter() } _pictureSettings = currentSettings; _needToProcess = _pictureSettings.Hue != 0 || _pictureSettings.Saturation != 0 || _pictureSettings.Brightness || _pictureSettings.Contrast; + + if(_needToProcess) { + double y, i, q; + uint32_t* originalPalette = _console->GetSettings()->GetRgbPalette(); + + for(int pal = 0; pal < 512; pal++) { + uint32_t pixelOutput = originalPalette[pal]; + double redChannel = ((pixelOutput & 0xFF0000) >> 16) / 255.0; + double greenChannel = ((pixelOutput & 0xFF00) >> 8) / 255.0; + double blueChannel = (pixelOutput & 0xFF) / 255.0; + + //Apply brightness, contrast, hue & saturation + RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q); + y *= _pictureSettings.Contrast * 0.5f + 1; + y += _pictureSettings.Brightness * 0.5f; + YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel); + + int r = std::min(255, (int)(redChannel * 255)); + int g = std::min(255, (int)(greenChannel * 255)); + int b = std::min(255, (int)(blueChannel * 255)); + + _calculatedPalette[pal] = 0xFF000000 | (r << 16) | (g << 8) | b; + } + } else { + memcpy(_calculatedPalette, _console->GetSettings()->GetRgbPalette(), sizeof(_calculatedPalette)); + } } void DefaultVideoFilter::DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines) { uint32_t* out = outputBuffer; OverscanDimensions overscan = GetOverscan(); - double scanlineIntensity = 1.0 - _console->GetSettings()->GetPictureSettings().ScanlineIntensity; + uint8_t scanlineIntensity = (uint8_t)((1.0 - _console->GetSettings()->GetPictureSettings().ScanlineIntensity) * 255); for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) { if(displayScanlines && (i + overscan.Top) % 2 == 0) { for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) { - *out = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j], scanlineIntensity); + *out = ApplyScanlineEffect(ppuOutputBuffer[i * 256 + j], scanlineIntensity); out++; } } else { for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) { - *out = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j]); + *out = _calculatedPalette[ppuOutputBuffer[i * 256 + j]]; out++; } } @@ -91,37 +117,13 @@ void DefaultVideoFilter::YiqToRgb(double y, double i, double q, double &r, doubl b = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[4] * i + _yiqToRgbMatrix[5] * q))); } -uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity) +uint32_t DefaultVideoFilter::ApplyScanlineEffect(uint16_t ppuPixel, uint8_t scanlineIntensity) { - uint32_t pixelOutput = _console->GetSettings()->GetRgbPalette()[ppuPixel & 0x1FF]; + uint32_t pixelOutput = _calculatedPalette[ppuPixel]; - if(_needToProcess || scanlineIntensity < 1.0) { - //Incorrect emphasis bit implementation, but will do for now. - double redChannel = ((pixelOutput & 0xFF0000) >> 16) / 255.0; - double greenChannel = ((pixelOutput & 0xFF00) >> 8) / 255.0; - double blueChannel = (pixelOutput & 0xFF) / 255.0; + uint8_t r = ((pixelOutput & 0xFF0000) >> 16) * scanlineIntensity / 255; + uint8_t g = ((pixelOutput & 0xFF00) >> 8) * scanlineIntensity / 255; + uint8_t b = (pixelOutput & 0xFF) * scanlineIntensity / 255; - //Apply brightness, contrast, hue & saturation - if(_needToProcess) { - double y, i, q; - RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q); - y *= _pictureSettings.Contrast * 0.5f + 1; - y += _pictureSettings.Brightness * 0.5f; - YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel); - } - - if(scanlineIntensity < 1.0) { - redChannel *= scanlineIntensity; - greenChannel *= scanlineIntensity; - blueChannel *= scanlineIntensity; - } - - int r = std::min(255, (int)(redChannel * 255)); - int g = std::min(255, (int)(greenChannel * 255)); - int b = std::min(255, (int)(blueChannel * 255)); - - return 0xFF000000 | (r << 16) | (g << 8) | b; - } else { - return pixelOutput; - } + return 0xFF000000 | (r << 16) | (g << 8) | b; } \ No newline at end of file diff --git a/Core/DefaultVideoFilter.h b/Core/DefaultVideoFilter.h index d53a54f5..4d3c44c7 100644 --- a/Core/DefaultVideoFilter.h +++ b/Core/DefaultVideoFilter.h @@ -7,6 +7,7 @@ class DefaultVideoFilter : public BaseVideoFilter { private: double _yiqToRgbMatrix[6]; + uint32_t _calculatedPalette[512]; PictureSettings _pictureSettings; bool _needToProcess = false; @@ -17,7 +18,7 @@ private: protected: void DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines); - uint32_t ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity = 1.0); + uint32_t ApplyScanlineEffect(uint16_t ppuPixel, uint8_t scanlineIntensity); void OnBeforeApplyFilter(); public: