GS: Redesign some of the offset code for FFMD

Half height buffers need to be drawn half height, not stretched to full height during the draw, it will be bad times.
This commit is contained in:
refractionpcsx2 2022-04-12 08:10:20 +01:00
parent e2044eba66
commit eed04b3ff3
3 changed files with 47 additions and 34 deletions

View File

@ -373,7 +373,7 @@ bool GSState::IsAnalogue()
return GetVideoMode() == GSVideoMode::NTSC || GetVideoMode() == GSVideoMode::PAL || GetVideoMode() == GSVideoMode::HDTV_1080I;
}
GSVector4i GSState::GetDisplayRectSize(int i)
GSVector4i GSState::GetDisplayMagnifiedRect(int i)
{
GSVector4i rectangle = { 0, 0, 0, 0 };
@ -394,9 +394,12 @@ GSVector4i GSState::GetDisplayRectSize(int i)
const int height = (DH / (VideoModeDividers[(int)videomode - 1].y + 1));
// Set up the display rectangle based on the values obtained from DISPLAY registers
const auto& SMODE2 = m_regs->SMODE2;
int res_multi = 1;
if (isinterlaced() && m_regs->SMODE2.FFMD && height > 1)
res_multi = 2;
rectangle.right = width;
rectangle.bottom = height;
rectangle.bottom = height / res_multi;
//DevCon.Warning("Display Rect Size Returning w %d h %d", width, height);
return rectangle;
}
@ -428,9 +431,11 @@ GSVector4i GSState::GetDisplayRect(int i)
const int width = DW / magnification.x;
const int height = DH / magnification.y;
const GSVector2i offsets = GetResolutionOffset(i);
// Set up the display rectangle based on the values obtained from DISPLAY registers
rectangle.left = DX;
rectangle.top = DY;
rectangle.left = offsets.x;
rectangle.top = offsets.y;
rectangle.right = rectangle.left + width;
rectangle.bottom = rectangle.top + height;
@ -449,13 +454,13 @@ GSVector2i GSState::GetResolutionOffset(int i)
GSVector2i offset;
offset.x = (((int)DISP.DX - VideoModeOffsets[(int)videomode - 1].z) / (VideoModeDividers[(int)videomode - 1].x + 1));
offset.y = (((int)DISP.DY - (VideoModeOffsets[(int)videomode - 1].w * (IsAnalogue() ? res_multi : 1))) / (VideoModeDividers[(int)videomode - 1].y + 1));
//DevCon.Warning("Res Offset X %d Video mode %d Y %d Video mode %d", DISP.DX, VideoModeOffsets[(int)videomode - 1].z, DISP.DY, (VideoModeOffsets[(int)videomode - 1].w * (IsAnalogue() ? res_multi : 1)));
offset.y = ((int)DISP.DY - (VideoModeOffsets[(int)videomode - 1].w * ((IsAnalogue() && res_multi) ? res_multi : 1))) / (VideoModeDividers[(int)videomode - 1].y + 1);
//DevCon.Warning("Res Offset X %d Video mode %d Y %d Video mode %d returning x %d y %d", DISP.DX, VideoModeOffsets[(int)videomode - 1].z, DISP.DY, (VideoModeOffsets[(int)videomode - 1].w * (IsAnalogue() ? res_multi : 1)), offset.x, offset.y);
return offset;
}
GSVector2i GSState::GetResolution()
GSVector2i GSState::GetResolution(bool include_interlace)
{
const GSVideoMode videomode = GetVideoMode();
const auto& SMODE2 = m_regs->SMODE2;
@ -464,7 +469,10 @@ GSVector2i GSState::GetResolution()
GSVector2i resolution;
resolution.x = VideoModeOffsets[(int)videomode - 1].x;
resolution.y = VideoModeOffsets[(int)videomode - 1].y * ((IsAnalogue() && res_multi) ? res_multi : 1);
resolution.y = VideoModeOffsets[(int)videomode - 1].y;
if(include_interlace && !m_regs->SMODE2.FFMD)
resolution.y *= ((IsAnalogue() && res_multi) ? res_multi : 1);
//DevCon.Warning("Getting Resolution X %d Y %d", resolution.x, resolution.y);
return resolution;
}
@ -475,7 +483,7 @@ GSVector4i GSState::GetFrameRect(int i)
if (i == -1)
return GetFrameRect(0).runion(GetFrameRect(1));
GSVector4i rectangle = GetDisplayRect(i);
GSVector4i rectangle;
const auto& DISP = m_regs->DISP[i].DISPLAY;
@ -492,16 +500,15 @@ GSVector4i GSState::GetFrameRect(int i)
rectangle.left = DBX;
rectangle.top = DBY;
rectangle.right = rectangle.left + w;
rectangle.bottom = rectangle.top + h;
if (isinterlaced() && m_regs->SMODE2.FFMD && h > 1)
{
h >>= 1;
rectangle.bottom >>= 1;
}
// Round down as this is the reading rect, so we want 0-639 and 0-479 for an example
rectangle.right = rectangle.left + w - 1;
rectangle.bottom = rectangle.top + h - 1;
//DevCon.Warning("Frame Rect left %d right %d top %d bottom %d DBX %d DBY %d", rectangle.left, rectangle.right, rectangle.top, rectangle.bottom, DBX, DBY);
//DevCon.Warning("Frame %d Rect left %d right %d top %d bottom %d DBX %d DBY %d", i, rectangle.left, rectangle.right, rectangle.top, rectangle.bottom, DBX, DBY);
return rectangle;
}

View File

@ -289,9 +289,9 @@ public:
int GetFramebufferHeight();
GSVector4i GetDisplayRect(int i = -1);
GSVector4i GetDisplayRectSize(int i = -1);
GSVector4i GetDisplayMagnifiedRect(int i = -1);
GSVector2i GetResolutionOffset(int i = -1);
GSVector2i GetResolution();
GSVector2i GetResolution(bool include_interlace = false);
GSVector4i GetFrameRect(int i = -1);
GSVideoMode GetVideoMode();

View File

@ -89,8 +89,8 @@ bool GSRenderer::Merge(int field)
fr[i] = GetFrameRect(i);
dr[i] = GetDisplayRect(i);
display_combined.x = std::max(GetDisplayRectSize(i).right + abs(GetResolutionOffset(i).x), display_combined.x);
display_combined.y = std::max(GetDisplayRectSize(i).bottom + abs(GetResolutionOffset(i).y), display_combined.y);
display_combined.x = std::max(GetDisplayMagnifiedRect(i).right + abs(GetResolutionOffset(i).x), display_combined.x);
display_combined.y = std::max(GetDisplayMagnifiedRect(i).bottom + abs(GetResolutionOffset(i).y), display_combined.y);
display_baseline.x = std::min(dr[i].left, display_baseline.x);
display_baseline.y = std::min(dr[i].top, display_baseline.y);
frame_baseline.x = std::min(fr[i].left, frame_baseline.x);
@ -196,8 +196,8 @@ bool GSRenderer::Merge(int field)
if (!en[i] || !tex[i])
continue;
const GSVector2i resolution(GetResolution());
GSVector4i r = GetDisplayRectSize(i);
const GSVector2i resolution(GetResolution(true));
GSVector4i r = GetDisplayMagnifiedRect(i);
GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy();
bool ignore_offset = !GSConfig.PCRTCOffsets;
@ -217,15 +217,13 @@ bool GSRenderer::Merge(int field)
if (!ignore_offset)
off.y &= ~1;
}
display_diff.x /= (VideoModeDividers[(int)videomode - 1].x + 1);
display_diff.y /= (VideoModeDividers[(int)videomode - 1].y + 1);
if (!ignore_offset && display_combined.y < resolution.y && display_combined.x < resolution.x)
if (!ignore_offset && display_combined.y < (resolution.y-1) && display_combined.x < (resolution.x-1))
{
float difference[2];
difference[0] = resolution.x / (float)display_combined.x;
difference[1] = resolution.y / (float)display_combined.y;
//DevCon.Warning("Difference x %f y %f old size x %d y %d res x %d y %d off x %d y %d", difference[0], difference[1], r.right, r.bottom, resolution.x, resolution.y, off.x, off.y);
if (difference[0] > 1.0f)
{
@ -330,17 +328,23 @@ bool GSRenderer::Merge(int field)
if (frame_diff.y == 1)
off.y += 1;
}
if (m_regs->SMODE2.INT && m_regs->SMODE2.FFMD)
{
off.y /= 2;
}
// Src is the size for output
src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy();
src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy();;
// Src_hw is the size which we're really reading
src_hw[i] = (GSVector4(fr[i]) + GSVector4(0, y_offset[i], 0, y_offset[i])) * scale / GSVector4(tex[i]->GetSize()).xyxy();
dst[i] = scale * (GSVector4(off).xyxy() + GSVector4(r.rsize()));
dst[i] = GSVector4(off).xyxy() + (scale * GSVector4(r.rsize()));
if (m_scanmask_used && interlace_offset)
dst[i] += GSVector4(0.0f, 1.0f, 0.0f, 1.0f);
//DevCon.Warning("Offset final x %d y %d Display x %d y %d Frame x %d y %d rect x %d y %d z %d w %d", off.x, off.y, display_diff.x, display_diff.x, frame_diff.y, frame_diff.y, r.x, r.y, r.z, r.w);
dst[i] -= GSVector4(0.0f, 1.0f, 0.0f, 1.0f);
//DevCon.Warning("Offset final x %d y %d Display Diff x %d y %d Frame Diff x %d y %d Frame Rect x %d y %d z %d w %d Display rect x %d y %d z %d w %d", off.x, off.y, display_diff.x, display_diff.x, frame_diff.y, frame_diff.y, fr[i].x, fr[i].y, fr[i].z, fr[i].w, r.x, r.y, r.z, r.w);
}
if (feedback_merge && tex[2])
@ -356,15 +360,17 @@ bool GSRenderer::Merge(int field)
dst[2] = GSVector4(scale * GSVector4(feedback_rect.rsize()));
}
fs = GetResolution() * GSVector2i(GetUpscaleMultiplier());
fs = GetResolution(true) * GSVector2i(GetUpscaleMultiplier());
//DevCon.Warning("Res x %d y %d", fs.x, fs.y);
ds = fs;
m_real_size = ds;
if (m_regs->SMODE2.INT && m_regs->SMODE2.FFMD)
{
ds.y *= 2;
}
m_real_size = ds;
if (tex[0] || tex[1])
{
if ((tex[0] == tex[1]) && (src[0] == src[1]).alltrue() && (dst[0] == dst[1]).alltrue() && !feedback_merge && !slbg)