diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 78be8c208e..5e4dda014d 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -453,9 +453,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con { wxGridSizer* const szr_stereo = new wxGridSizer(2, 5, 5); - const wxString stereo_choices[] = { "Off", "Side-by-Side", "Anaglyph" }; + const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", "Anaglyph" }; szr_stereo->Add(new wxStaticText(page_enh, -1, _("Stereo 3D Mode:")), 1, wxALIGN_CENTER_VERTICAL, 0); - szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), 3, stereo_choices)); + szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), 4, stereo_choices)); wxSlider* const sep_slider = new wxSlider(page_enh, wxID_ANY, vconfig.iStereoSeparation, 30, 90, wxDefaultPosition, wxDefaultSize, wxSL_VALUE_LABEL); sep_slider->Bind(wxEVT_SLIDER, &VideoConfigDiag::Event_StereoSep, this); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 484232f3cc..ff6f9f25df 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1514,19 +1514,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co sourceRc.right -= fbStride - fbWidth; - if (g_ActiveConfig.iStereoMode == STEREO_SBS) + if (g_ActiveConfig.iStereoMode == STEREO_SBS || g_ActiveConfig.iStereoMode == STEREO_TAB) { - // Resize target to half its original size - int width = drawRc.GetWidth(); - drawRc.left += width / 4; - drawRc.right -= width / 4; - - // Create two target rectangle offset to the sides of the backbuffer - TargetRectangle leftRc = drawRc, rightRc = drawRc; - leftRc.left -= s_backbuffer_width / 4; - leftRc.right -= s_backbuffer_width / 4; - rightRc.left += s_backbuffer_width / 4; - rightRc.right += s_backbuffer_width / 4; + TargetRectangle leftRc, rightRc; + ConvertStereoRectangle(flipped_trc, leftRc, rightRc); m_post_processor->BlitFromTexture(sourceRc, leftRc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight, 0); m_post_processor->BlitFromTexture(sourceRc, rightRc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight, 1); @@ -1544,19 +1535,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co // for msaa mode, we must resolve the efb content to non-msaa GLuint tex = FramebufferManager::ResolveAndGetRenderTarget(rc); - if (g_ActiveConfig.iStereoMode == STEREO_SBS) + if (g_ActiveConfig.iStereoMode == STEREO_SBS || g_ActiveConfig.iStereoMode == STEREO_TAB) { - // Resize target to half its original size - int width = flipped_trc.GetWidth(); - flipped_trc.left += width / 4; - flipped_trc.right -= width / 4; - - // Create two target rectangle offset to the sides of the backbuffer - TargetRectangle leftRc = flipped_trc, rightRc = flipped_trc; - leftRc.left -= s_backbuffer_width / 4; - leftRc.right -= s_backbuffer_width / 4; - rightRc.left += s_backbuffer_width / 4; - rightRc.right += s_backbuffer_width / 4; + TargetRectangle leftRc, rightRc; + ConvertStereoRectangle(flipped_trc, leftRc, rightRc); m_post_processor->BlitFromTexture(targetRc, leftRc, tex, s_target_width, s_target_height, 0); m_post_processor->BlitFromTexture(targetRc, rightRc, tex, s_target_width, s_target_height, 1); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index d93d43f490..84c037c753 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -240,6 +240,42 @@ bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int return false; } +void Renderer::ConvertStereoRectangle(const TargetRectangle& rc, TargetRectangle& leftRc, TargetRectangle& rightRc) +{ + // Resize target to half its original size + TargetRectangle drawRc = rc; + if (g_ActiveConfig.iStereoMode == STEREO_TAB) + { + // The height may be negative due to flipped rectangles + int height = rc.bottom - rc.top; + drawRc.top += height / 4; + drawRc.bottom -= height / 4; + } + else + { + int width = rc.right - rc.left; + drawRc.left += width / 4; + drawRc.right -= width / 4; + } + + // Create two target rectangle offset to the sides of the backbuffer + leftRc = drawRc, rightRc = drawRc; + if (g_ActiveConfig.iStereoMode == STEREO_TAB) + { + leftRc.top -= s_backbuffer_height / 4; + leftRc.bottom -= s_backbuffer_height / 4; + rightRc.top += s_backbuffer_height / 4; + rightRc.bottom += s_backbuffer_height / 4; + } + else + { + leftRc.left -= s_backbuffer_width / 4; + leftRc.right -= s_backbuffer_width / 4; + rightRc.left += s_backbuffer_width / 4; + rightRc.right += s_backbuffer_width / 4; + } +} + void Renderer::SetScreenshot(const std::string& filename) { std::lock_guard lk(s_criticalScreenshot); diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 746f75366c..f59458e523 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -83,6 +83,8 @@ public: static const TargetRectangle& GetTargetRectangle() { return target_rc; } static void UpdateDrawRectangle(int backbuffer_width, int backbuffer_height); + // Use this to convert a single target rectangle to two stereo rectangles + static void ConvertStereoRectangle(const TargetRectangle& rc, TargetRectangle& leftRc, TargetRectangle& rightRc); // Use this to upscale native EFB coordinates to IDEAL internal resolution static int EFBToScaledX(int x); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index a03e70bdc6..994264e58e 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -48,6 +48,7 @@ enum StereoMode { STEREO_OFF = 0, STEREO_SBS, + STEREO_TAB, STEREO_ANAGLYPH };