mirror of https://github.com/PCSX2/pcsx2.git
GS: Clean up new DISPLAY Merging code.
This commit is contained in:
parent
eed04b3ff3
commit
7cdc849ffa
|
@ -373,7 +373,7 @@ bool GSState::IsAnalogue()
|
|||
return GetVideoMode() == GSVideoMode::NTSC || GetVideoMode() == GSVideoMode::PAL || GetVideoMode() == GSVideoMode::HDTV_1080I;
|
||||
}
|
||||
|
||||
GSVector4i GSState::GetDisplayMagnifiedRect(int i)
|
||||
GSVector4i GSState::GetFrameMagnifiedRect(int i)
|
||||
{
|
||||
GSVector4i rectangle = { 0, 0, 0, 0 };
|
||||
|
||||
|
@ -393,14 +393,16 @@ GSVector4i GSState::GetDisplayMagnifiedRect(int i)
|
|||
const int width = (DW / (VideoModeDividers[(int)videomode - 1].x + 1));
|
||||
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;
|
||||
|
||||
// Set up the display rectangle based on the values obtained from DISPLAY registers
|
||||
rectangle.right = width;
|
||||
rectangle.bottom = height / res_multi;
|
||||
//DevCon.Warning("Display Rect Size Returning w %d h %d", width, height);
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
|
@ -420,9 +422,6 @@ GSVector4i GSState::GetDisplayRect(int i)
|
|||
|
||||
const u32 DW = DISP.DW + 1;
|
||||
const u32 DH = DISP.DH + 1;
|
||||
const u32 DX = DISP.DX;
|
||||
const u32 DY = DISP.DY;
|
||||
|
||||
const u32 MAGH = DISP.MAGH + 1;
|
||||
const u32 MAGV = DISP.MAGV + 1;
|
||||
|
||||
|
@ -432,6 +431,7 @@ GSVector4i GSState::GetDisplayRect(int i)
|
|||
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 = offsets.x;
|
||||
rectangle.top = offsets.y;
|
||||
|
@ -439,8 +439,6 @@ GSVector4i GSState::GetDisplayRect(int i)
|
|||
rectangle.right = rectangle.left + width;
|
||||
rectangle.bottom = rectangle.top + height;
|
||||
|
||||
//DevCon.Warning("left %d offset %d total %d top %d offset %d total %d", rectangle.left, VideoModeOffsets[(int)videomode - 1].z, (rectangle.left - VideoModeOffsets[(int)videomode - 1].z) / magnification.x, rectangle.top, (VideoModeOffsets[(int)videomode - 1].w / magnification.y) * (IsAnalogue() ? res_multi : 1), v_offset);
|
||||
//DevCon.Warning("Get Display Rect Left %d Right %d Top %d Bottom %d", rectangle.left, rectangle.right, rectangle.top, rectangle.bottom);
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
|
@ -455,12 +453,11 @@ GSVector2i GSState::GetResolutionOffset(int i)
|
|||
|
||||
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) ? 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(bool include_interlace)
|
||||
GSVector2i GSState::GetResolution()
|
||||
{
|
||||
const GSVideoMode videomode = GetVideoMode();
|
||||
const auto& SMODE2 = m_regs->SMODE2;
|
||||
|
@ -471,9 +468,9 @@ GSVector2i GSState::GetResolution(bool include_interlace)
|
|||
resolution.x = VideoModeOffsets[(int)videomode - 1].x;
|
||||
resolution.y = VideoModeOffsets[(int)videomode - 1].y;
|
||||
|
||||
if(include_interlace && !m_regs->SMODE2.FFMD)
|
||||
if(!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;
|
||||
}
|
||||
|
||||
|
@ -504,11 +501,7 @@ GSVector4i GSState::GetFrameRect(int i)
|
|||
rectangle.bottom = rectangle.top + h;
|
||||
|
||||
if (isinterlaced() && m_regs->SMODE2.FFMD && h > 1)
|
||||
{
|
||||
rectangle.bottom >>= 1;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
|
|
@ -289,9 +289,9 @@ public:
|
|||
|
||||
int GetFramebufferHeight();
|
||||
GSVector4i GetDisplayRect(int i = -1);
|
||||
GSVector4i GetDisplayMagnifiedRect(int i = -1);
|
||||
GSVector4i GetFrameMagnifiedRect(int i = -1);
|
||||
GSVector2i GetResolutionOffset(int i = -1);
|
||||
GSVector2i GetResolution(bool include_interlace = false);
|
||||
GSVector2i GetResolution();
|
||||
GSVector4i GetFrameRect(int i = -1);
|
||||
GSVideoMode GetVideoMode();
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ bool GSRenderer::Merge(int field)
|
|||
|
||||
GSVector4i fr[2];
|
||||
GSVector4i dr[2];
|
||||
GSVector2i display_offsets[2];
|
||||
|
||||
GSVector2i display_baseline = {INT_MAX, INT_MAX};
|
||||
GSVector2i frame_baseline = {INT_MAX, INT_MAX};
|
||||
|
@ -88,9 +89,10 @@ bool GSRenderer::Merge(int field)
|
|||
{
|
||||
fr[i] = GetFrameRect(i);
|
||||
dr[i] = GetDisplayRect(i);
|
||||
display_offsets[i] = GetResolutionOffset(i);
|
||||
|
||||
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_combined.x = std::max(GetFrameMagnifiedRect(i).right + abs(display_offsets[i].x), display_combined.x);
|
||||
display_combined.y = std::max(GetFrameMagnifiedRect(i).bottom + abs(display_offsets[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);
|
||||
|
@ -185,46 +187,50 @@ bool GSRenderer::Merge(int field)
|
|||
tex[2] = GetFeedbackOutput();
|
||||
}
|
||||
|
||||
GSVector4 src[2];
|
||||
GSVector4 src_hw[2];
|
||||
GSVector4 src_out_rect[2];
|
||||
GSVector4 src_gs_read[2];
|
||||
GSVector4 dst[3];
|
||||
|
||||
const bool slbg = m_regs->PMODE.SLBG;
|
||||
|
||||
const GSVector2i resolution(GetResolution());
|
||||
const GSVideoMode videomode = GetVideoMode();
|
||||
|
||||
bool scanmask_frame = true;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (!en[i] || !tex[i])
|
||||
continue;
|
||||
|
||||
const GSVector2i resolution(GetResolution(true));
|
||||
GSVector4i r = GetDisplayMagnifiedRect(i);
|
||||
GSVector4i r = GetFrameMagnifiedRect(i);
|
||||
GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy();
|
||||
|
||||
bool ignore_offset = !GSConfig.PCRTCOffsets;
|
||||
const bool ignore_offset = !GSConfig.PCRTCOffsets;
|
||||
|
||||
GSVector2i off(ignore_offset ? 0 : GetResolutionOffset(i));
|
||||
GSVector2i off(ignore_offset ? 0 : display_offsets[i]);
|
||||
GSVector2i display_diff(dr[i].left - display_baseline.x, dr[i].top - display_baseline.y);
|
||||
GSVector2i frame_diff(fr[i].left - frame_baseline.x, fr[i].top - frame_baseline.y);
|
||||
|
||||
const GSVideoMode videomode = GetVideoMode();
|
||||
|
||||
// If using scanmsk we have to keep the single line offset, regardless of upscale
|
||||
// so we handle this separately after the rect calculations.
|
||||
const int interlace_offset = display_diff.y & 1;
|
||||
|
||||
if (m_scanmask_used && interlace_offset)
|
||||
{
|
||||
display_diff.y &= ~1;
|
||||
|
||||
scanmask_frame = false;
|
||||
if (!ignore_offset)
|
||||
off.y &= ~1;
|
||||
}
|
||||
|
||||
|
||||
// All the following code is literally just to try and fill the window as much as possible and reduce blur put in by gamedevs by offsetting the DISPLAY's.
|
||||
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)
|
||||
{
|
||||
float difference_to_use = (difference[0] < difference[1]) ? difference[0] : difference[1];
|
||||
|
@ -251,15 +257,14 @@ bool GSRenderer::Merge(int field)
|
|||
off.y -= display_diff.y;
|
||||
}
|
||||
}
|
||||
else if(ignore_offset)// Stretch to fit the window
|
||||
else if(ignore_offset) // Stretch to fit the window.
|
||||
{
|
||||
float difference[2];
|
||||
|
||||
//If the picture is offset we want to make sure we don't make it bigger, so this is the only place we need to now about the offset!
|
||||
difference[0] = resolution.x / (float)((display_combined.x - GetResolutionOffset(i).x) + display_diff.x);
|
||||
difference[1] = resolution.y / (float)((display_combined.y - GetResolutionOffset(i).y) + display_diff.y);
|
||||
difference[0] = resolution.x / (float)((display_combined.x - display_offsets[i].x) + display_diff.x);
|
||||
difference[1] = resolution.y / (float)((display_combined.y - display_offsets[i].y) + display_diff.y);
|
||||
|
||||
//DevCon.Warning("Difference x %f y %f old size x %d y %d res x %d y %d off x %d y %d disp diff x %d y %d comb x %d y %d res off x %d y %d", difference[0], difference[1], r.right, r.bottom, resolution.x, resolution.y, off.x, off.y, display_diff.x, display_diff.y, display_combined.x, display_combined.y, GetResolutionOffset(i).x, GetResolutionOffset(i).y);
|
||||
if (difference[0] > 1.0f)
|
||||
{
|
||||
const float difference_to_use = difference[0];
|
||||
|
@ -275,7 +280,7 @@ bool GSRenderer::Merge(int field)
|
|||
{
|
||||
r.bottom += height_change;
|
||||
}
|
||||
// Anti blur hax
|
||||
// Anti blur hax.
|
||||
if (!slbg || !feedback_merge)
|
||||
{
|
||||
if (display_diff.x > 4)
|
||||
|
@ -315,7 +320,7 @@ bool GSRenderer::Merge(int field)
|
|||
}
|
||||
}
|
||||
}
|
||||
// Anti blur hax
|
||||
// Anti blur hax.
|
||||
else if (samesrc)
|
||||
{
|
||||
if (display_diff.x < 4)
|
||||
|
@ -328,23 +333,24 @@ bool GSRenderer::Merge(int field)
|
|||
if (frame_diff.y == 1)
|
||||
off.y += 1;
|
||||
}
|
||||
|
||||
// End of Resize/Anti-Blur code.
|
||||
|
||||
// Offsets are in full rect form, needs resizing for the actual draw if interlaced half frame.
|
||||
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_gs_read is the size which we're really reading from GS memory.
|
||||
src_gs_read[i] = (GSVector4(fr[i]) + GSVector4(0, y_offset[i], 0, y_offset[i])) * 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();
|
||||
// src_out_rect is the resized rect for output.
|
||||
src_out_rect[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy();
|
||||
|
||||
dst[i] = GSVector4(off).xyxy() + (scale * GSVector4(r.rsize()));
|
||||
// dst is the final destination rect with offset on the screen.
|
||||
dst[i] = scale * (GSVector4(off).xyxy() + GSVector4(r.rsize()));
|
||||
|
||||
// Restore the single line offset for scanmsk.
|
||||
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 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])
|
||||
|
@ -360,10 +366,10 @@ bool GSRenderer::Merge(int field)
|
|||
dst[2] = GSVector4(scale * GSVector4(feedback_rect.rsize()));
|
||||
}
|
||||
|
||||
fs = GetResolution(true) * GSVector2i(GetUpscaleMultiplier());
|
||||
//DevCon.Warning("Res x %d y %d", fs.x, fs.y);
|
||||
fs = resolution * GSVector2i(GetUpscaleMultiplier());
|
||||
ds = fs;
|
||||
|
||||
// When interlace(FRAME) mode, the rect is half height, so it needs to be stretched.
|
||||
if (m_regs->SMODE2.INT && m_regs->SMODE2.FFMD)
|
||||
{
|
||||
ds.y *= 2;
|
||||
|
@ -373,7 +379,7 @@ bool GSRenderer::Merge(int field)
|
|||
|
||||
if (tex[0] || tex[1])
|
||||
{
|
||||
if ((tex[0] == tex[1]) && (src[0] == src[1]).alltrue() && (dst[0] == dst[1]).alltrue() && !feedback_merge && !slbg)
|
||||
if ((tex[0] == tex[1]) && (src_out_rect[0] == src_out_rect[1]).alltrue() && (dst[0] == dst[1]).alltrue() && !feedback_merge && !slbg)
|
||||
{
|
||||
// the two outputs are identical, skip drawing one of them (the one that is alpha blended)
|
||||
|
||||
|
@ -382,11 +388,11 @@ bool GSRenderer::Merge(int field)
|
|||
|
||||
GSVector4 c = GSVector4((int)m_regs->BGCOLOR.R, (int)m_regs->BGCOLOR.G, (int)m_regs->BGCOLOR.B, (int)m_regs->PMODE.ALP) / 255;
|
||||
|
||||
g_gs_device->Merge(tex, src_hw, dst, fs, m_regs->PMODE, m_regs->EXTBUF, c);
|
||||
g_gs_device->Merge(tex, src_gs_read, dst, fs, m_regs->PMODE, m_regs->EXTBUF, c);
|
||||
|
||||
if (m_regs->SMODE2.INT && GSConfig.InterlaceMode != GSInterlaceMode::Off)
|
||||
{
|
||||
const bool scanmask = m_scanmask_used && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
||||
const bool scanmask = m_scanmask_used && scanmask_frame && GSConfig.InterlaceMode == GSInterlaceMode::Automatic;
|
||||
|
||||
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic && (m_regs->SMODE2.FFMD)) // Auto interlace enabled / Odd frame interlace setting
|
||||
{
|
||||
|
@ -398,7 +404,7 @@ bool GSRenderer::Merge(int field)
|
|||
{
|
||||
const int field2 = scanmask ? 0 : 0 - ((static_cast<int>(GSConfig.InterlaceMode) - 1) & 1);
|
||||
const int offset = tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y;
|
||||
int mode = scanmask ? 2 : ((static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1);
|
||||
const int mode = scanmask ? 2 : ((static_cast<int>(GSConfig.InterlaceMode) - 1) >> 1);
|
||||
|
||||
g_gs_device->Interlace(ds, field ^ field2, mode, offset);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue