Qt: Add crop options

This commit is contained in:
Connor McLaughlin 2022-06-29 22:45:01 +10:00 committed by refractionpcsx2
parent 54d284cdac
commit f88756cb53
5 changed files with 106 additions and 21 deletions

View File

@ -116,8 +116,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.internalResolutionScreenshots, "EmuCore/GS", "InternalResolutionScreenshots", false);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.stretchY, "EmuCore/GS", "StretchY", 100.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.offsetX, "EmuCore/GS", "OffsetX", 0.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.offsetY, "EmuCore/GS", "OffsetY", 0.0f);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropLeft, "EmuCore/GS", "CropLeft", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropTop, "EmuCore/GS", "CropTop", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropRight, "EmuCore/GS", "CropRight", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropBottom, "EmuCore/GS", "CropBottom", 0);
connect(m_ui.integerScaling, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onIntegerScalingChanged);
onIntegerScalingChanged();

View File

@ -234,14 +234,21 @@
<item row="6" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Offset:</string>
<string>Crop:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,0,1">
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,1,0,1,0,1,0,1">
<item>
<widget class="QSpinBox" name="offsetX">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Left:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="cropLeft">
<property name="suffix">
<string>px</string>
</property>
@ -253,12 +260,46 @@
<item>
<widget class="QLabel" name="label_25">
<property name="text">
<string>x</string>
<string>Top:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="offsetY">
<widget class="QSpinBox" name="cropTop">
<property name="suffix">
<string>px</string>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_40">
<property name="text">
<string>Right:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="cropRight">
<property name="suffix">
<string>px</string>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_41">
<property name="text">
<string>Bottom:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="cropBottom">
<property name="suffix">
<string>px</string>
</property>

View File

@ -516,8 +516,12 @@ struct Pcsx2Config
double Zoom{100.0};
double StretchY{100.0};
#ifndef PCSX2_CORE
double OffsetX{0.0};
double OffsetY{0.0};
#else
int Crop[4]{};
#endif
double OsdScale{100.0};

View File

@ -407,7 +407,7 @@ static float GetCurrentAspectRatioFloat(bool is_progressive)
return ars[static_cast<u32>(GSConfig.AspectRatio) + (3u * (is_progressive && GSConfig.AspectRatio == AspectRatioType::RAuto4_3_3_2))];
}
static GSVector4 CalculateDrawRect(s32 window_width, s32 window_height, s32 texture_width, s32 texture_height, HostDisplay::Alignment alignment, bool flip_y, bool is_progressive)
static GSVector4 CalculateDrawDstRect(s32 window_width, s32 window_height, const GSVector4i& src_rect, const GSVector2i& src_size, HostDisplay::Alignment alignment, bool flip_y, bool is_progressive)
{
const float f_width = static_cast<float>(window_width);
const float f_height = static_cast<float>(window_height);
@ -428,7 +428,10 @@ static GSVector4 CalculateDrawRect(s32 window_width, s32 window_height, s32 text
else if (EmuConfig.CurrentAspectRatio == AspectRatioType::R16_9)
targetAr = 16.0f / 9.0f;
const double arr = targetAr / clientAr;
const float crop_adjust = (static_cast<float>(src_rect.width()) / static_cast<float>(src_size.x)) /
(static_cast<float>(src_rect.height()) / static_cast<float>(src_size.y));
const double arr = (targetAr * crop_adjust) / clientAr;
float target_width = f_width;
float target_height = f_height;
if (arr < 1)
@ -446,8 +449,8 @@ static GSVector4 CalculateDrawRect(s32 window_width, s32 window_height, s32 text
if (GSConfig.IntegerScaling)
{
// make target width/height an integer multiple of the texture width/height
const float t_width = static_cast<double>(texture_width);
const float t_height = static_cast<double>(texture_height);
const float t_width = static_cast<double>(src_rect.width());
const float t_height = static_cast<double>(src_rect.height());
float scale;
if ((t_width / t_height) >= 1.0)
@ -505,9 +508,11 @@ static GSVector4 CalculateDrawRect(s32 window_width, s32 window_height, s32 text
}
}
#ifndef PCSX2_CORE
const float unit = .01f * std::min(target_x, target_y);
target_x += unit * GSConfig.OffsetX;
target_y += unit * GSConfig.OffsetY;
#endif
GSVector4 ret(target_x, target_y, target_x + target_width, target_y + target_height);
@ -521,6 +526,21 @@ static GSVector4 CalculateDrawRect(s32 window_width, s32 window_height, s32 text
return ret;
}
static GSVector4i CalculateDrawSrcRect(const GSTexture* src)
{
#ifndef PCSX2_CORE
return GSVector4i(0, 0, src->GetWidth(), src->GetHeight());
#else
const int upscale = GSConfig.UpscaleMultiplier;
const GSVector2i size(src->GetSize());
const int left = GSConfig.Crop[0] * upscale;
const int top = GSConfig.Crop[1] * upscale;
const int right = size.x - (GSConfig.Crop[2] * upscale);
const int bottom = size.y - (GSConfig.Crop[3] * upscale);
return GSVector4i(left, top, right, bottom);
#endif
}
void GSRenderer::VSync(u32 field, bool registers_written)
{
Flush();
@ -586,13 +606,16 @@ void GSRenderer::VSync(u32 field, bool registers_written)
if (current && !blank_frame)
{
HostDisplay* const display = g_gs_device->GetDisplay();
const GSVector4 draw_rect(CalculateDrawRect(display->GetWindowWidth(), display->GetWindowHeight(),
current->GetWidth(), current->GetHeight(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(), GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
const GSVector4i src_rect(CalculateDrawSrcRect(current));
const GSVector4 src_uv(GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy());
const GSVector4 draw_rect(CalculateDrawDstRect(display->GetWindowWidth(), display->GetWindowHeight(),
src_rect, current->GetSize(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(),
GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
const u64 current_time = Common::Timer::GetCurrentValue();
const float shader_time = static_cast<float>(Common::Timer::ConvertValueToSeconds(current_time - m_shader_time_start));
g_gs_device->PresentRect(current, GSVector4(0, 0, 1, 1), nullptr, draw_rect,
g_gs_device->PresentRect(current, src_uv, nullptr, draw_rect,
s_tv_shader_indices[GSConfig.TVShader], shader_time, GSConfig.LinearPresent);
}
@ -786,13 +809,16 @@ void GSRenderer::PresentCurrentFrame()
if (current)
{
HostDisplay* const display = g_gs_device->GetDisplay();
const GSVector4 draw_rect(CalculateDrawRect(display->GetWindowWidth(), display->GetWindowHeight(),
current->GetWidth(), current->GetHeight(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(), GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
const GSVector4i src_rect(CalculateDrawSrcRect(current));
const GSVector4 src_uv(GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy());
const GSVector4 draw_rect(CalculateDrawDstRect(display->GetWindowWidth(), display->GetWindowHeight(),
src_rect, current->GetSize(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(),
GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
const u64 current_time = Common::Timer::GetCurrentValue();
const float shader_time = static_cast<float>(Common::Timer::ConvertValueToSeconds(current_time - m_shader_time_start));
g_gs_device->PresentRect(current, GSVector4(0, 0, 1, 1), nullptr, draw_rect,
g_gs_device->PresentRect(current, src_uv, nullptr, draw_rect,
s_tv_shader_indices[GSConfig.TVShader], shader_time, GSConfig.LinearPresent);
}
@ -907,7 +933,9 @@ bool GSRenderer::SaveSnapshotToMemory(u32 width, u32 height, std::vector<u32>* p
if (!current)
return false;
GSVector4 draw_rect(CalculateDrawRect(width, height, current->GetWidth(), current->GetHeight(),
const GSVector4i src_rect(CalculateDrawSrcRect(current));
const GSVector4 src_uv(GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy());
GSVector4 draw_rect(CalculateDrawDstRect(width, height, src_rect, current->GetSize(),
HostDisplay::Alignment::LeftOrTop, false, GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
u32 draw_width = static_cast<u32>(draw_rect.z - draw_rect.x);
u32 draw_height = static_cast<u32>(draw_rect.w - draw_rect.y);
@ -926,7 +954,7 @@ bool GSRenderer::SaveSnapshotToMemory(u32 width, u32 height, std::vector<u32>* p
GSTexture::GSMap map;
const bool result = g_gs_device->DownloadTextureConvert(
current, GSVector4(0.0f, 0.0f, 1.0f, 1.0f),
current, src_uv,
GSVector2i(draw_width, draw_height), GSTexture::Format::Color,
ShaderConvert::COPY, map, true);
if (result)

View File

@ -385,8 +385,16 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
OpEqu(Zoom) &&
OpEqu(StretchY) &&
#ifndef PCSX2_CORE
OpEqu(OffsetX) &&
OpEqu(OffsetY) &&
#else
OpEqu(Crop[0]) &&
OpEqu(Crop[1]) &&
OpEqu(Crop[2]) &&
OpEqu(Crop[3]) &&
#endif
OpEqu(OsdScale) &&
OpEqu(Renderer) &&
@ -469,8 +477,10 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapEntry(Zoom);
SettingsWrapEntry(StretchY);
SettingsWrapEntry(OffsetX);
SettingsWrapEntry(OffsetY);
SettingsWrapEntryEx(Crop[0], "CropLeft");
SettingsWrapEntryEx(Crop[1], "CropTop");
SettingsWrapEntryEx(Crop[2], "CropRight");
SettingsWrapEntryEx(Crop[3], "CropBottom");
#endif
#ifndef PCSX2_CORE