mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-22 03:57:17 +01:00
Renderer: Adjust source rectangle when crop would draw off screen
This prevents us from requiring an oversized and/or negative viewport by shrinking the source rectangle instead.
This commit is contained in:
parent
d2d8d7ce90
commit
3c64f0c616
@ -338,12 +338,14 @@ void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const MathUtil:
|
|||||||
// Render to staging texture which is double the width of the backbuffer
|
// Render to staging texture which is double the width of the backbuffer
|
||||||
SetAndClearFramebuffer(m_3d_vision_framebuffer.get());
|
SetAndClearFramebuffer(m_3d_vision_framebuffer.get());
|
||||||
|
|
||||||
const auto target_rc = GetTargetRectangle();
|
auto adjusted_rc = rc;
|
||||||
m_post_processor->BlitFromTexture(target_rc, rc, texture, 0);
|
auto target_rc = GetTargetRectangle();
|
||||||
|
AdjustRectanglesToFitBounds(&target_rc, &adjusted_rc, m_backbuffer_width, m_backbuffer_height);
|
||||||
|
m_post_processor->BlitFromTexture(target_rc, adjusted_rc, texture, 0);
|
||||||
m_post_processor->BlitFromTexture(
|
m_post_processor->BlitFromTexture(
|
||||||
MathUtil::Rectangle<int>(target_rc.left + m_backbuffer_width, target_rc.top,
|
MathUtil::Rectangle<int>(target_rc.left + m_backbuffer_width, target_rc.top,
|
||||||
target_rc.right + m_backbuffer_width, target_rc.bottom),
|
target_rc.right + m_backbuffer_width, target_rc.bottom),
|
||||||
rc, texture, 1);
|
adjusted_rc, texture, 1);
|
||||||
|
|
||||||
// Copy the left eye to the backbuffer, if Nvidia 3D Vision is enabled it should
|
// Copy the left eye to the backbuffer, if Nvidia 3D Vision is enabled it should
|
||||||
// recognize the signature and automatically include the right eye frame.
|
// recognize the signature and automatically include the right eye frame.
|
||||||
|
@ -984,13 +984,15 @@ void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const MathUtil:
|
|||||||
if (g_ActiveConfig.stereo_mode != StereoMode::QuadBuffer)
|
if (g_ActiveConfig.stereo_mode != StereoMode::QuadBuffer)
|
||||||
return ::Renderer::RenderXFBToScreen(texture, rc);
|
return ::Renderer::RenderXFBToScreen(texture, rc);
|
||||||
|
|
||||||
const auto target_rc = GetTargetRectangle();
|
auto adjusted_rc = rc;
|
||||||
|
auto target_rc = GetTargetRectangle();
|
||||||
|
AdjustRectanglesToFitBounds(&target_rc, &adjusted_rc, m_backbuffer_width, m_backbuffer_height);
|
||||||
|
|
||||||
glDrawBuffer(GL_BACK_LEFT);
|
glDrawBuffer(GL_BACK_LEFT);
|
||||||
m_post_processor->BlitFromTexture(target_rc, rc, texture, 0);
|
m_post_processor->BlitFromTexture(target_rc, adjusted_rc, texture, 0);
|
||||||
|
|
||||||
glDrawBuffer(GL_BACK_RIGHT);
|
glDrawBuffer(GL_BACK_RIGHT);
|
||||||
m_post_processor->BlitFromTexture(target_rc, rc, texture, 1);
|
m_post_processor->BlitFromTexture(target_rc, adjusted_rc, texture, 1);
|
||||||
|
|
||||||
glDrawBuffer(GL_BACK);
|
glDrawBuffer(GL_BACK);
|
||||||
}
|
}
|
||||||
|
@ -561,6 +561,40 @@ float Renderer::CalculateDrawAspectRatio() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::AdjustRectanglesToFitBounds(MathUtil::Rectangle<int>* target_rect,
|
||||||
|
MathUtil::Rectangle<int>* source_rect, int fb_width,
|
||||||
|
int fb_height)
|
||||||
|
{
|
||||||
|
const int orig_target_width = target_rect->GetWidth();
|
||||||
|
const int orig_target_height = target_rect->GetHeight();
|
||||||
|
const int orig_source_width = source_rect->GetWidth();
|
||||||
|
const int orig_source_height = source_rect->GetHeight();
|
||||||
|
if (target_rect->left < 0)
|
||||||
|
{
|
||||||
|
const int offset = -target_rect->left;
|
||||||
|
target_rect->left = 0;
|
||||||
|
source_rect->left += offset * orig_source_width / orig_target_width;
|
||||||
|
}
|
||||||
|
if (target_rect->right > fb_width)
|
||||||
|
{
|
||||||
|
const int offset = target_rect->right - fb_width;
|
||||||
|
target_rect->right -= offset;
|
||||||
|
source_rect->right -= offset * orig_source_width / orig_target_width;
|
||||||
|
}
|
||||||
|
if (target_rect->top < 0)
|
||||||
|
{
|
||||||
|
const int offset = -target_rect->top;
|
||||||
|
target_rect->top = 0;
|
||||||
|
source_rect->top += offset * orig_source_height / orig_target_height;
|
||||||
|
}
|
||||||
|
if (target_rect->bottom > fb_height)
|
||||||
|
{
|
||||||
|
const int offset = target_rect->bottom - fb_height;
|
||||||
|
target_rect->right -= offset;
|
||||||
|
source_rect->right -= offset * orig_source_height / orig_target_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Renderer::IsHeadless() const
|
bool Renderer::IsHeadless() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -1287,19 +1321,21 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6
|
|||||||
|
|
||||||
void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const MathUtil::Rectangle<int>& rc)
|
void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const MathUtil::Rectangle<int>& rc)
|
||||||
{
|
{
|
||||||
const auto target_rc = GetTargetRectangle();
|
auto adjusted_rc = rc;
|
||||||
|
auto target_rc = GetTargetRectangle();
|
||||||
|
AdjustRectanglesToFitBounds(&target_rc, &adjusted_rc, m_backbuffer_width, m_backbuffer_height);
|
||||||
if (g_ActiveConfig.stereo_mode == StereoMode::SBS ||
|
if (g_ActiveConfig.stereo_mode == StereoMode::SBS ||
|
||||||
g_ActiveConfig.stereo_mode == StereoMode::TAB)
|
g_ActiveConfig.stereo_mode == StereoMode::TAB)
|
||||||
{
|
{
|
||||||
MathUtil::Rectangle<int> left_rc, right_rc;
|
MathUtil::Rectangle<int> left_rc, right_rc;
|
||||||
std::tie(left_rc, right_rc) = ConvertStereoRectangle(target_rc);
|
std::tie(left_rc, right_rc) = ConvertStereoRectangle(target_rc);
|
||||||
|
|
||||||
m_post_processor->BlitFromTexture(left_rc, rc, texture, 0);
|
m_post_processor->BlitFromTexture(left_rc, adjusted_rc, texture, 0);
|
||||||
m_post_processor->BlitFromTexture(right_rc, rc, texture, 1);
|
m_post_processor->BlitFromTexture(right_rc, adjusted_rc, texture, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_post_processor->BlitFromTexture(target_rc, rc, texture, 0);
|
m_post_processor->BlitFromTexture(target_rc, adjusted_rc, texture, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,13 @@ public:
|
|||||||
const MathUtil::Rectangle<int>& GetTargetRectangle() const { return m_target_rectangle; }
|
const MathUtil::Rectangle<int>& GetTargetRectangle() const { return m_target_rectangle; }
|
||||||
float CalculateDrawAspectRatio() const;
|
float CalculateDrawAspectRatio() const;
|
||||||
|
|
||||||
|
// Crops the target rectangle to the framebuffer dimensions, reducing the size of the source
|
||||||
|
// rectangle if it is greater. Works even if the source and target rectangles don't have a
|
||||||
|
// 1:1 pixel mapping, scaling as appropriate.
|
||||||
|
void AdjustRectanglesToFitBounds(MathUtil::Rectangle<int>* target_rect,
|
||||||
|
MathUtil::Rectangle<int>* source_rect, int fb_width,
|
||||||
|
int fb_height);
|
||||||
|
|
||||||
std::tuple<float, float> ScaleToDisplayAspectRatio(int width, int height) const;
|
std::tuple<float, float> ScaleToDisplayAspectRatio(int width, int height) const;
|
||||||
void UpdateDrawRectangle();
|
void UpdateDrawRectangle();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user