mirror of https://github.com/PCSX2/pcsx2.git
GS-HW: Scale display texture width in TC.
This commit is contained in:
parent
b74f91b868
commit
4ef879d1f2
|
@ -575,6 +575,20 @@ int GSState::GetFramebufferHeight()
|
||||||
return frame_memory_height;
|
return frame_memory_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GSState::GetFramebufferWidth()
|
||||||
|
{
|
||||||
|
// Framebuffer height is 11 bits max
|
||||||
|
constexpr int width_limit = (1 << 11);
|
||||||
|
|
||||||
|
const GSVector4i disp1_rect = GetFrameRect(0, true);
|
||||||
|
const GSVector4i disp2_rect = GetFrameRect(1, true);
|
||||||
|
const GSVector4i combined = disp1_rect.runion(disp2_rect);
|
||||||
|
|
||||||
|
const int max_width = std::max(disp1_rect.width(), disp2_rect.width());
|
||||||
|
|
||||||
|
return max_width;
|
||||||
|
}
|
||||||
|
|
||||||
bool GSState::IsEnabled(int i)
|
bool GSState::IsEnabled(int i)
|
||||||
{
|
{
|
||||||
ASSERT(i >= 0 && i < 2);
|
ASSERT(i >= 0 && i < 2);
|
||||||
|
|
|
@ -322,6 +322,7 @@ public:
|
||||||
void ResetHandlers();
|
void ResetHandlers();
|
||||||
|
|
||||||
int GetFramebufferHeight();
|
int GetFramebufferHeight();
|
||||||
|
int GetFramebufferWidth();
|
||||||
int GetDisplayHMagnification();
|
int GetDisplayHMagnification();
|
||||||
GSVector4i GetDisplayRect(int i = -1);
|
GSVector4i GetDisplayRect(int i = -1);
|
||||||
GSVector4i GetFrameMagnifiedRect(int i = -1);
|
GSVector4i GetFrameMagnifiedRect(int i = -1);
|
||||||
|
|
|
@ -239,10 +239,11 @@ GSTexture* GSRendererHW::GetOutput(int i, int& y_offset)
|
||||||
|
|
||||||
const int videomode = static_cast<int>(GetVideoMode()) - 1;
|
const int videomode = static_cast<int>(GetVideoMode()) - 1;
|
||||||
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
|
const GSVector4i offsets = !GSConfig.PCRTCOverscan ? VideoModeOffsets[videomode] : VideoModeOffsetsOverscan[videomode];
|
||||||
|
|
||||||
|
const int fb_width = std::min<int>(std::min<int>(GetFramebufferWidth(), DISPFB.FBW * 64) + (int)DISPFB.DBX, 2048);
|
||||||
const int display_height = offsets.y * ((isinterlaced() && !m_regs->SMODE2.FFMD) ? 2 : 1);
|
const int display_height = offsets.y * ((isinterlaced() && !m_regs->SMODE2.FFMD) ? 2 : 1);
|
||||||
const int display_offset = GetResolutionOffset(i).y;
|
const int display_offset = GetResolutionOffset(i).y;
|
||||||
int fb_height = std::min<int>(std::min<int>(GetFramebufferHeight(), display_height) + (int)DISPFB.DBY, 2048);
|
int fb_height = std::min<int>(std::min<int>(GetFramebufferHeight(), display_height) + (int)DISPFB.DBY, 2048);
|
||||||
|
|
||||||
// If there is a negative vertical offset on the picture, we need to read more.
|
// If there is a negative vertical offset on the picture, we need to read more.
|
||||||
if (display_offset < 0)
|
if (display_offset < 0)
|
||||||
{
|
{
|
||||||
|
@ -253,11 +254,7 @@ GSTexture* GSRendererHW::GetOutput(int i, int& y_offset)
|
||||||
GSTexture* t = nullptr;
|
GSTexture* t = nullptr;
|
||||||
GSVector2i size = GetOutputSize(fb_height);
|
GSVector2i size = GetOutputSize(fb_height);
|
||||||
|
|
||||||
// Expand read horizontally if offset in to the texture. (Causes visible stretching on FMVs otherwise)
|
if (GSTextureCache::Target* rt = m_tc->LookupDisplayTarget(TEX0, GetOutputSize(fb_height), fb_height, fb_width))
|
||||||
if (DISPFB.DBX)
|
|
||||||
size.x += DISPFB.DBX;
|
|
||||||
|
|
||||||
if (GSTextureCache::Target* rt = m_tc->LookupDisplayTarget(TEX0, size, fb_height))
|
|
||||||
{
|
{
|
||||||
t = rt->m_texture;
|
t = rt->m_texture;
|
||||||
|
|
||||||
|
@ -293,7 +290,12 @@ GSTexture* GSRendererHW::GetFeedbackOutput()
|
||||||
TEX0.PSM = m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPFB.PSM;
|
TEX0.PSM = m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPFB.PSM;
|
||||||
|
|
||||||
const int fb_height = /*GetFrameRect(i).bottom*/ m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPLAY.DH;
|
const int fb_height = /*GetFrameRect(i).bottom*/ m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPLAY.DH;
|
||||||
GSTextureCache::Target* rt = m_tc->LookupDisplayTarget(TEX0, GetOutputSize(fb_height), fb_height);
|
GSVector2i size = GetOutputSize(fb_height);
|
||||||
|
|
||||||
|
if (m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPFB.DBX)
|
||||||
|
size.x += m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPFB.DBX * static_cast<int>(GSConfig.UpscaleMultiplier);
|
||||||
|
|
||||||
|
GSTextureCache::Target* rt = m_tc->LookupDisplayTarget(TEX0, GetOutputSize(fb_height), fb_height, size.x);
|
||||||
|
|
||||||
GSTexture* t = rt->m_texture;
|
GSTexture* t = rt->m_texture;
|
||||||
|
|
||||||
|
|
|
@ -414,7 +414,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_h)
|
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_h, const int real_w)
|
||||||
{
|
{
|
||||||
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
|
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
|
||||||
const GSVector2& new_s = static_cast<GSRendererHW*>(g_gs_renderer.get())->GetTextureScaleFactor();
|
const GSVector2& new_s = static_cast<GSRendererHW*>(g_gs_renderer.get())->GetTextureScaleFactor();
|
||||||
|
@ -469,8 +469,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
|
||||||
{
|
{
|
||||||
dst = t;
|
dst = t;
|
||||||
GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: %d (0x%x -> 0x%x %s)", size.x, size.y, dst->m_texture->GetID(), bp, t->m_end_block, psm_str(TEX0.PSM));
|
GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: %d (0x%x -> 0x%x %s)", size.x, size.y, dst->m_texture->GetID(), bp, t->m_end_block, psm_str(TEX0.PSM));
|
||||||
if (real_h > 0)
|
if (real_h > 0 || real_w > 0)
|
||||||
ScaleTargetForDisplay(dst, TEX0, real_h);
|
ScaleTargetForDisplay(dst, TEX0, real_h, real_w);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -485,8 +485,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
|
||||||
{
|
{
|
||||||
dst = t;
|
dst = t;
|
||||||
GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: %d (0x%x, took 0x%x -> 0x%x %s)", size.x, size.y, t->m_texture->GetID(), bp, t->m_TEX0.TBP0, t->m_end_block, psm_str(TEX0.PSM));
|
GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: %d (0x%x, took 0x%x -> 0x%x %s)", size.x, size.y, t->m_texture->GetID(), bp, t->m_TEX0.TBP0, t->m_end_block, psm_str(TEX0.PSM));
|
||||||
if (real_h > 0)
|
if (real_h > 0 || real_w > 0)
|
||||||
ScaleTargetForDisplay(dst, TEX0, real_h);
|
ScaleTargetForDisplay(dst, TEX0, real_h, real_w);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -623,12 +623,12 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_h)
|
GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_h, const int real_w)
|
||||||
{
|
{
|
||||||
return LookupTarget(TEX0, size, RenderTarget, true, 0, true, real_h);
|
return LookupTarget(TEX0, size, RenderTarget, true, 0, true, real_h, real_w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_h)
|
void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_h, int real_w)
|
||||||
{
|
{
|
||||||
// This handles a case where you have two images stacked on top of one another (usually FMVs), and
|
// This handles a case where you have two images stacked on top of one another (usually FMVs), and
|
||||||
// the size of the top framebuffer is larger than the height of the image. Usually happens when
|
// the size of the top framebuffer is larger than the height of the image. Usually happens when
|
||||||
|
@ -656,11 +656,13 @@ void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb,
|
||||||
GSTexture* old_texture = t->m_texture;
|
GSTexture* old_texture = t->m_texture;
|
||||||
const int needed_height = std::min(real_h + y_offset, GSRendererHW::MAX_FRAMEBUFFER_HEIGHT);
|
const int needed_height = std::min(real_h + y_offset, GSRendererHW::MAX_FRAMEBUFFER_HEIGHT);
|
||||||
const int scaled_needed_height = static_cast<int>(static_cast<float>(needed_height) * old_texture->GetScale().y);
|
const int scaled_needed_height = static_cast<int>(static_cast<float>(needed_height) * old_texture->GetScale().y);
|
||||||
if (scaled_needed_height <= old_texture->GetHeight())
|
const int needed_width = std::min(real_w, static_cast<int>(dispfb.TBW * 64));
|
||||||
|
const int scaled_needed_width = static_cast<int>(static_cast<float>(needed_width) * old_texture->GetScale().x);
|
||||||
|
if (scaled_needed_height <= old_texture->GetHeight() && scaled_needed_width <= old_texture->GetWidth())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We're expanding, so create a new texture.
|
// We're expanding, so create a new texture.
|
||||||
GSTexture* new_texture = g_gs_device->CreateRenderTarget(old_texture->GetWidth(), scaled_needed_height, GSTexture::Format::Color, false);
|
GSTexture* new_texture = g_gs_device->CreateRenderTarget(scaled_needed_width, scaled_needed_height, GSTexture::Format::Color, false);
|
||||||
if (!new_texture)
|
if (!new_texture)
|
||||||
{
|
{
|
||||||
// Memory allocation failure, do our best to hobble along.
|
// Memory allocation failure, do our best to hobble along.
|
||||||
|
|
|
@ -311,7 +311,7 @@ protected:
|
||||||
|
|
||||||
/// Expands a target when the block pointer for a display framebuffer is within another target, but the read offset
|
/// Expands a target when the block pointer for a display framebuffer is within another target, but the read offset
|
||||||
/// plus the height is larger than the current size of the target.
|
/// plus the height is larger than the current size of the target.
|
||||||
void ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_h);
|
void ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_h, int real_w);
|
||||||
|
|
||||||
HashCacheEntry* LookupHashCache(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool& paltex, const u32* clut, const GSVector2i* lod);
|
HashCacheEntry* LookupHashCache(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool& paltex, const u32* clut, const GSVector2i* lod);
|
||||||
|
|
||||||
|
@ -335,8 +335,8 @@ public:
|
||||||
Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, const GSVector2i* lod);
|
Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, const GSVector2i* lod);
|
||||||
Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette = false);
|
Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette = false);
|
||||||
|
|
||||||
Target* LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask = 0, const bool is_frame = false, const int real_h = 0);
|
Target* LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask = 0, const bool is_frame = false, const int real_h = 0, const int real_w = 0);
|
||||||
Target* LookupDisplayTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_h);
|
Target* LookupDisplayTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_h, const int real_w);
|
||||||
|
|
||||||
/// Looks up a target in the cache, and only returns it if the BP/BW/PSM match exactly.
|
/// Looks up a target in the cache, and only returns it if the BP/BW/PSM match exactly.
|
||||||
Target* GetExactTarget(u32 BP, u32 BW, u32 PSM) const;
|
Target* GetExactTarget(u32 BP, u32 BW, u32 PSM) const;
|
||||||
|
|
Loading…
Reference in New Issue