Fixed issues with screenshots
This commit is contained in:
parent
b80d788346
commit
31502f6c16
7 changed files with 69 additions and 36 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include "../Utilities/FolderUtilities.h"
|
#include "../Utilities/FolderUtilities.h"
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include "StandardController.h"
|
#include "StandardController.h"
|
||||||
|
#include "ScaleFilter.h"
|
||||||
|
|
||||||
BaseVideoFilter::BaseVideoFilter()
|
BaseVideoFilter::BaseVideoFilter()
|
||||||
{
|
{
|
||||||
|
@ -60,28 +61,40 @@ uint8_t* BaseVideoFilter::GetOutputBuffer()
|
||||||
return _outputBuffer;
|
return _outputBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseVideoFilter::TakeScreenshot(string filename, std::stringstream *stream)
|
void BaseVideoFilter::TakeScreenshot(VideoFilterType filterType, string filename, std::stringstream *stream)
|
||||||
{
|
{
|
||||||
|
uint32_t* pngBuffer;
|
||||||
|
FrameInfo frameInfo;
|
||||||
uint32_t* frameBuffer = nullptr;
|
uint32_t* frameBuffer = nullptr;
|
||||||
{
|
{
|
||||||
auto lock = _frameLock.AcquireSafe();
|
auto lock = _frameLock.AcquireSafe();
|
||||||
if(_bufferSize == 0 || !GetOutputBuffer()) {
|
if(_bufferSize == 0 || !GetOutputBuffer()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
frameBuffer = (uint32_t*)new uint8_t[_bufferSize];
|
frameBuffer = (uint32_t*)new uint8_t[_bufferSize];
|
||||||
memcpy(frameBuffer, GetOutputBuffer(), _bufferSize);
|
memcpy(frameBuffer, GetOutputBuffer(), _bufferSize);
|
||||||
|
frameInfo = GetFrameInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ScaleFilter> scaleFilter = ScaleFilter::GetScaleFilter(filterType);
|
||||||
|
if(scaleFilter) {
|
||||||
|
pngBuffer = scaleFilter->ApplyFilter(frameBuffer, frameInfo.Width, frameInfo.Height);
|
||||||
|
frameInfo = scaleFilter->GetFrameInfo(frameInfo);
|
||||||
|
} else {
|
||||||
|
pngBuffer = frameBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!filename.empty()) {
|
if(!filename.empty()) {
|
||||||
PNGHelper::WritePNG(filename, frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
|
PNGHelper::WritePNG(filename, pngBuffer, frameInfo.Width, frameInfo.Height);
|
||||||
} else {
|
} else {
|
||||||
PNGHelper::WritePNG(*stream, frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
|
PNGHelper::WritePNG(*stream, pngBuffer, frameInfo.Width, frameInfo.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] frameBuffer;
|
delete[] frameBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseVideoFilter::TakeScreenshot()
|
void BaseVideoFilter::TakeScreenshot(VideoFilterType filterType)
|
||||||
{
|
{
|
||||||
string romFilename = FolderUtilities::GetFilename(Console::GetRomName(), false);
|
string romFilename = FolderUtilities::GetFilename(Console::GetRomName(), false);
|
||||||
|
|
||||||
|
@ -103,7 +116,7 @@ void BaseVideoFilter::TakeScreenshot()
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
TakeScreenshot(ssFilename);
|
TakeScreenshot(filterType, ssFilename);
|
||||||
|
|
||||||
MessageManager::DisplayMessage("ScreenshotSaved", FolderUtilities::GetFilename(ssFilename, true));
|
MessageManager::DisplayMessage("ScreenshotSaved", FolderUtilities::GetFilename(ssFilename, true));
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ public:
|
||||||
|
|
||||||
uint8_t* GetOutputBuffer();
|
uint8_t* GetOutputBuffer();
|
||||||
void SendFrame(uint16_t *ppuOutputBuffer);
|
void SendFrame(uint16_t *ppuOutputBuffer);
|
||||||
void TakeScreenshot();
|
void TakeScreenshot(VideoFilterType filterType);
|
||||||
void TakeScreenshot(string filename, std::stringstream *stream = nullptr);
|
void TakeScreenshot(VideoFilterType filterType, string filename, std::stringstream *stream = nullptr);
|
||||||
|
|
||||||
virtual OverscanDimensions GetOverscan();
|
virtual OverscanDimensions GetOverscan();
|
||||||
virtual FrameInfo GetFrameInfo() = 0;
|
virtual FrameInfo GetFrameInfo() = 0;
|
||||||
|
|
|
@ -97,4 +97,43 @@ uint32_t* ScaleFilter::ApplyFilter(uint32_t *inputArgbBuffer, uint32_t width, ui
|
||||||
}
|
}
|
||||||
|
|
||||||
return _outputBuffer;
|
return _outputBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ScaleFilter> ScaleFilter::GetScaleFilter(VideoFilterType filter)
|
||||||
|
{
|
||||||
|
shared_ptr<ScaleFilter> scaleFilter;
|
||||||
|
switch(filter) {
|
||||||
|
case VideoFilterType::xBRZ2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 2)); break;
|
||||||
|
case VideoFilterType::xBRZ3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 3)); break;
|
||||||
|
case VideoFilterType::xBRZ4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 4)); break;
|
||||||
|
case VideoFilterType::xBRZ5x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 5)); break;
|
||||||
|
case VideoFilterType::xBRZ6x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 6)); break;
|
||||||
|
case VideoFilterType::HQ2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 2)); break;
|
||||||
|
case VideoFilterType::HQ3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 3)); break;
|
||||||
|
case VideoFilterType::HQ4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 4)); break;
|
||||||
|
case VideoFilterType::Scale2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 2)); break;
|
||||||
|
case VideoFilterType::Scale3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 3)); break;
|
||||||
|
case VideoFilterType::Scale4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 4)); break;
|
||||||
|
case VideoFilterType::_2xSai: scaleFilter.reset(new ScaleFilter(ScaleFilterType::_2xSai, 2)); break;
|
||||||
|
case VideoFilterType::Super2xSai: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Super2xSai, 2)); break;
|
||||||
|
case VideoFilterType::SuperEagle: scaleFilter.reset(new ScaleFilter(ScaleFilterType::SuperEagle, 2)); break;
|
||||||
|
|
||||||
|
case VideoFilterType::Prescale2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 2)); break;
|
||||||
|
case VideoFilterType::Prescale3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 3)); break;
|
||||||
|
case VideoFilterType::Prescale4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 4)); break;
|
||||||
|
case VideoFilterType::Prescale6x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 6)); break;
|
||||||
|
case VideoFilterType::Prescale8x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 8)); break;
|
||||||
|
case VideoFilterType::Prescale10x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 10)); break;
|
||||||
|
}
|
||||||
|
return scaleFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameInfo ScaleFilter::GetFrameInfo(FrameInfo baseFrameInfo)
|
||||||
|
{
|
||||||
|
FrameInfo info = baseFrameInfo;
|
||||||
|
info.Height *= this->GetScale();
|
||||||
|
info.Width *= this->GetScale();
|
||||||
|
info.OriginalHeight *= this->GetScale();
|
||||||
|
info.OriginalWidth *= this->GetScale();
|
||||||
|
return info;
|
||||||
}
|
}
|
|
@ -22,4 +22,7 @@ public:
|
||||||
|
|
||||||
uint32_t GetScale();
|
uint32_t GetScale();
|
||||||
uint32_t* ApplyFilter(uint32_t *inputArgbBuffer, uint32_t width, uint32_t height);
|
uint32_t* ApplyFilter(uint32_t *inputArgbBuffer, uint32_t width, uint32_t height);
|
||||||
|
FrameInfo GetFrameInfo(FrameInfo baseFrameInfo);
|
||||||
|
|
||||||
|
static shared_ptr<ScaleFilter> GetScaleFilter(VideoFilterType filter);
|
||||||
};
|
};
|
|
@ -72,31 +72,12 @@ void VideoDecoder::UpdateVideoFilter()
|
||||||
_scaleFilter.reset();
|
_scaleFilter.reset();
|
||||||
|
|
||||||
switch(_videoFilterType) {
|
switch(_videoFilterType) {
|
||||||
|
case VideoFilterType::None: break;
|
||||||
case VideoFilterType::NTSC: _videoFilter.reset(new NtscFilter()); break;
|
case VideoFilterType::NTSC: _videoFilter.reset(new NtscFilter()); break;
|
||||||
case VideoFilterType::BisqwitNtsc: _videoFilter.reset(new BisqwitNtscFilter(1)); break;
|
case VideoFilterType::BisqwitNtsc: _videoFilter.reset(new BisqwitNtscFilter(1)); break;
|
||||||
case VideoFilterType::BisqwitNtscHalfRes: _videoFilter.reset(new BisqwitNtscFilter(2)); break;
|
case VideoFilterType::BisqwitNtscHalfRes: _videoFilter.reset(new BisqwitNtscFilter(2)); break;
|
||||||
case VideoFilterType::BisqwitNtscQuarterRes: _videoFilter.reset(new BisqwitNtscFilter(4)); break;
|
case VideoFilterType::BisqwitNtscQuarterRes: _videoFilter.reset(new BisqwitNtscFilter(4)); break;
|
||||||
case VideoFilterType::xBRZ2x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 2)); break;
|
default: _scaleFilter = ScaleFilter::GetScaleFilter(_videoFilterType); break;
|
||||||
case VideoFilterType::xBRZ3x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 3)); break;
|
|
||||||
case VideoFilterType::xBRZ4x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 4)); break;
|
|
||||||
case VideoFilterType::xBRZ5x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 5)); break;
|
|
||||||
case VideoFilterType::xBRZ6x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 6)); break;
|
|
||||||
case VideoFilterType::HQ2x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 2)); break;
|
|
||||||
case VideoFilterType::HQ3x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 3)); break;
|
|
||||||
case VideoFilterType::HQ4x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 4)); break;
|
|
||||||
case VideoFilterType::Scale2x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 2)); break;
|
|
||||||
case VideoFilterType::Scale3x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 3)); break;
|
|
||||||
case VideoFilterType::Scale4x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 4)); break;
|
|
||||||
case VideoFilterType::_2xSai: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::_2xSai, 2)); break;
|
|
||||||
case VideoFilterType::Super2xSai: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Super2xSai, 2)); break;
|
|
||||||
case VideoFilterType::SuperEagle: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::SuperEagle, 2)); break;
|
|
||||||
|
|
||||||
case VideoFilterType::Prescale2x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 2)); break;
|
|
||||||
case VideoFilterType::Prescale3x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 3)); break;
|
|
||||||
case VideoFilterType::Prescale4x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 4)); break;
|
|
||||||
case VideoFilterType::Prescale6x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 6)); break;
|
|
||||||
case VideoFilterType::Prescale8x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 8)); break;
|
|
||||||
case VideoFilterType::Prescale10x: _scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 10)); break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_hdFilterEnabled = false;
|
_hdFilterEnabled = false;
|
||||||
|
@ -131,10 +112,7 @@ void VideoDecoder::DecodeFrame()
|
||||||
|
|
||||||
FrameInfo frameInfo = _videoFilter->GetFrameInfo();
|
FrameInfo frameInfo = _videoFilter->GetFrameInfo();
|
||||||
if(_scaleFilter) {
|
if(_scaleFilter) {
|
||||||
frameInfo.Height *= _scaleFilter->GetScale();
|
frameInfo = _scaleFilter->GetFrameInfo(frameInfo);
|
||||||
frameInfo.Width *= _scaleFilter->GetScale();
|
|
||||||
frameInfo.OriginalHeight *= _scaleFilter->GetScale();
|
|
||||||
frameInfo.OriginalWidth *= _scaleFilter->GetScale();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_frameChanged = false;
|
_frameChanged = false;
|
||||||
|
@ -245,13 +223,13 @@ bool VideoDecoder::IsRunning()
|
||||||
void VideoDecoder::TakeScreenshot()
|
void VideoDecoder::TakeScreenshot()
|
||||||
{
|
{
|
||||||
if(_videoFilter) {
|
if(_videoFilter) {
|
||||||
_videoFilter->TakeScreenshot();
|
_videoFilter->TakeScreenshot(_videoFilterType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoDecoder::TakeScreenshot(std::stringstream &stream)
|
void VideoDecoder::TakeScreenshot(std::stringstream &stream)
|
||||||
{
|
{
|
||||||
if(_videoFilter) {
|
if(_videoFilter) {
|
||||||
_videoFilter->TakeScreenshot("", &stream);
|
_videoFilter->TakeScreenshot(_videoFilterType, "", &stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ private:
|
||||||
|
|
||||||
VideoFilterType _videoFilterType = VideoFilterType::None;
|
VideoFilterType _videoFilterType = VideoFilterType::None;
|
||||||
unique_ptr<BaseVideoFilter> _videoFilter;
|
unique_ptr<BaseVideoFilter> _videoFilter;
|
||||||
unique_ptr<ScaleFilter> _scaleFilter;
|
shared_ptr<ScaleFilter> _scaleFilter;
|
||||||
|
|
||||||
void UpdateVideoFilter();
|
void UpdateVideoFilter();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ bool PNGHelper::WritePNG(std::stringstream &stream, uint32_t* buffer, uint32_t x
|
||||||
//ARGB -> ABGR
|
//ARGB -> ABGR
|
||||||
uint32_t size = xSize * ySize * bitsPerPixel / 8 / 4;
|
uint32_t size = xSize * ySize * bitsPerPixel / 8 / 4;
|
||||||
for(uint32_t i = 0; i < size; i++) {
|
for(uint32_t i = 0; i < size; i++) {
|
||||||
buffer[i] = (buffer[i] & 0xFF00FF00) | ((buffer[i] & 0xFF0000) >> 16) | ((buffer[i] & 0xFF) << 16);
|
buffer[i] = 0xFF000000 | (buffer[i] & 0x00FF00) | ((buffer[i] & 0xFF0000) >> 16) | ((buffer[i] & 0xFF) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pngData = tdefl_write_image_to_png_file_in_memory_ex(buffer, xSize, ySize, bitsPerPixel / 8, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE);
|
void *pngData = tdefl_write_image_to_png_file_in_memory_ex(buffer, xSize, ySize, bitsPerPixel / 8, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE);
|
||||||
|
|
Loading…
Add table
Reference in a new issue