Merge pull request #3632 from N00byKing/3dtv_botenable
Add Support for Stereoscopic 3D
This commit is contained in:
commit
574824a26c
10 changed files with 115 additions and 19 deletions
|
@ -108,6 +108,10 @@ void Config::ReadValues() {
|
||||||
Settings::values.frame_limit =
|
Settings::values.frame_limit =
|
||||||
static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100));
|
static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100));
|
||||||
|
|
||||||
|
Settings::values.toggle_3d = sdl2_config->GetBoolean("Renderer", "toggle_3d", false);
|
||||||
|
Settings::values.factor_3d =
|
||||||
|
static_cast<u8>(sdl2_config->GetInteger("Renderer", "factor_3d", 0));
|
||||||
|
|
||||||
Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 0.0);
|
Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 0.0);
|
||||||
Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 0.0);
|
Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 0.0);
|
||||||
Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 0.0);
|
Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 0.0);
|
||||||
|
|
|
@ -116,6 +116,14 @@ bg_red =
|
||||||
bg_blue =
|
bg_blue =
|
||||||
bg_green =
|
bg_green =
|
||||||
|
|
||||||
|
# Toggles Stereoscopic 3D
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
toggle_3d =
|
||||||
|
|
||||||
|
# Change 3D Intensity
|
||||||
|
# 0 - 100: Intensity. 0 (default)
|
||||||
|
factor_3d =
|
||||||
|
|
||||||
[Layout]
|
[Layout]
|
||||||
# Layout for the screen inside the render window.
|
# Layout for the screen inside the render window.
|
||||||
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
||||||
|
|
|
@ -100,6 +100,8 @@ void Config::ReadValues() {
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
||||||
qt_config->beginGroup("Layout");
|
qt_config->beginGroup("Layout");
|
||||||
|
Settings::values.toggle_3d = qt_config->value("toggle_3d", false).toBool();
|
||||||
|
Settings::values.factor_3d = qt_config->value("factor_3d", 0).toInt();
|
||||||
Settings::values.layout_option =
|
Settings::values.layout_option =
|
||||||
static_cast<Settings::LayoutOption>(qt_config->value("layout_option").toInt());
|
static_cast<Settings::LayoutOption>(qt_config->value("layout_option").toInt());
|
||||||
Settings::values.swap_screen = qt_config->value("swap_screen", false).toBool();
|
Settings::values.swap_screen = qt_config->value("swap_screen", false).toBool();
|
||||||
|
@ -323,6 +325,8 @@ void Config::SaveValues() {
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
||||||
qt_config->beginGroup("Layout");
|
qt_config->beginGroup("Layout");
|
||||||
|
qt_config->setValue("toggle_3d", Settings::values.toggle_3d);
|
||||||
|
qt_config->setValue("factor_3d", Settings::values.factor_3d);
|
||||||
qt_config->setValue("layout_option", static_cast<int>(Settings::values.layout_option));
|
qt_config->setValue("layout_option", static_cast<int>(Settings::values.layout_option));
|
||||||
qt_config->setValue("swap_screen", Settings::values.swap_screen);
|
qt_config->setValue("swap_screen", Settings::values.swap_screen);
|
||||||
qt_config->setValue("custom_layout", Settings::values.custom_layout);
|
qt_config->setValue("custom_layout", Settings::values.custom_layout);
|
||||||
|
|
|
@ -40,6 +40,8 @@ void ConfigureGraphics::setConfiguration() {
|
||||||
ui->toggle_vsync->setChecked(Settings::values.use_vsync);
|
ui->toggle_vsync->setChecked(Settings::values.use_vsync);
|
||||||
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
|
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
|
||||||
ui->frame_limit->setValue(Settings::values.frame_limit);
|
ui->frame_limit->setValue(Settings::values.frame_limit);
|
||||||
|
ui->factor_3d->setValue(Settings::values.factor_3d);
|
||||||
|
ui->toggle_3d->setChecked(Settings::values.toggle_3d);
|
||||||
ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option));
|
ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option));
|
||||||
ui->swap_screen->setChecked(Settings::values.swap_screen);
|
ui->swap_screen->setChecked(Settings::values.swap_screen);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +57,8 @@ void ConfigureGraphics::applyConfiguration() {
|
||||||
Settings::values.use_vsync = ui->toggle_vsync->isChecked();
|
Settings::values.use_vsync = ui->toggle_vsync->isChecked();
|
||||||
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
|
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
|
||||||
Settings::values.frame_limit = ui->frame_limit->value();
|
Settings::values.frame_limit = ui->frame_limit->value();
|
||||||
|
Settings::values.factor_3d = ui->factor_3d->value();
|
||||||
|
Settings::values.toggle_3d = ui->toggle_3d->isChecked();
|
||||||
Settings::values.layout_option =
|
Settings::values.layout_option =
|
||||||
static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex());
|
static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex());
|
||||||
Settings::values.swap_screen = ui->swap_screen->isChecked();
|
Settings::values.swap_screen = ui->swap_screen->isChecked();
|
||||||
|
|
|
@ -228,6 +228,33 @@
|
||||||
<string>Layout</string>
|
<string>Layout</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="toggle_3d">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable Stereoscopic 3D</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="factor_3d">
|
||||||
|
<property name="suffix">
|
||||||
|
<string>%</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -60,9 +60,17 @@ EmuWindow::~EmuWindow() {
|
||||||
*/
|
*/
|
||||||
static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x,
|
static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x,
|
||||||
unsigned framebuffer_y) {
|
unsigned framebuffer_y) {
|
||||||
return (
|
if (Settings::values.toggle_3d) {
|
||||||
framebuffer_y >= layout.bottom_screen.top && framebuffer_y < layout.bottom_screen.bottom &&
|
return (framebuffer_y >= layout.bottom_screen.top &&
|
||||||
framebuffer_x >= layout.bottom_screen.left && framebuffer_x < layout.bottom_screen.right);
|
framebuffer_y < layout.bottom_screen.bottom &&
|
||||||
|
framebuffer_x >= layout.bottom_screen.left / 2 &&
|
||||||
|
framebuffer_x < layout.bottom_screen.right / 2);
|
||||||
|
} else {
|
||||||
|
return (framebuffer_y >= layout.bottom_screen.top &&
|
||||||
|
framebuffer_y < layout.bottom_screen.bottom &&
|
||||||
|
framebuffer_x >= layout.bottom_screen.left &&
|
||||||
|
framebuffer_x < layout.bottom_screen.right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) {
|
std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) {
|
||||||
|
@ -80,9 +88,16 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(touch_state->mutex);
|
std::lock_guard<std::mutex> guard(touch_state->mutex);
|
||||||
|
if (Settings::values.toggle_3d) {
|
||||||
|
touch_state->touch_x =
|
||||||
|
static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) /
|
||||||
|
(framebuffer_layout.bottom_screen.right / 2 -
|
||||||
|
framebuffer_layout.bottom_screen.left / 2);
|
||||||
|
} else {
|
||||||
touch_state->touch_x =
|
touch_state->touch_x =
|
||||||
static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left) /
|
static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left) /
|
||||||
(framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left);
|
(framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left);
|
||||||
|
}
|
||||||
touch_state->touch_y =
|
touch_state->touch_y =
|
||||||
static_cast<float>(framebuffer_y - framebuffer_layout.bottom_screen.top) /
|
static_cast<float>(framebuffer_y - framebuffer_layout.bottom_screen.top) /
|
||||||
(framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
|
(framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/service/ptm/ptm.h"
|
#include "core/hle/service/ptm/ptm.h"
|
||||||
#include "core/hle/shared_page.h"
|
#include "core/hle/shared_page.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -83,6 +84,10 @@ void Init() {
|
||||||
update_time_event =
|
update_time_event =
|
||||||
CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
|
CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
|
||||||
CoreTiming::ScheduleEvent(0, update_time_event);
|
CoreTiming::ScheduleEvent(0, update_time_event);
|
||||||
|
|
||||||
|
float slidestate =
|
||||||
|
Settings::values.toggle_3d ? (float_le)Settings::values.factor_3d / 100 : 0.0f;
|
||||||
|
shared_page.sliderstate_3d = slidestate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMacAddress(const MacAddress& addr) {
|
void SetMacAddress(const MacAddress& addr) {
|
||||||
|
|
|
@ -132,6 +132,9 @@ struct Values {
|
||||||
float bg_green;
|
float bg_green;
|
||||||
float bg_blue;
|
float bg_blue;
|
||||||
|
|
||||||
|
bool toggle_3d;
|
||||||
|
u8 factor_3d;
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
std::string sink_id;
|
std::string sink_id;
|
||||||
bool enable_audio_stretching;
|
bool enable_audio_stretching;
|
||||||
|
|
|
@ -103,12 +103,13 @@ void RendererOpenGL::SwapBuffers() {
|
||||||
OpenGLState prev_state = OpenGLState::GetCurState();
|
OpenGLState prev_state = OpenGLState::GetCurState();
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
for (int i : {0, 1}) {
|
for (int i : {0, 1, 2}) {
|
||||||
const auto& framebuffer = GPU::g_regs.framebuffer_config[i];
|
int fb_id = i == 2 ? 1 : 0;
|
||||||
|
const auto& framebuffer = GPU::g_regs.framebuffer_config[fb_id];
|
||||||
|
|
||||||
// Main LCD (0): 0x1ED02204, Sub LCD (1): 0x1ED02A04
|
// Main LCD (0): 0x1ED02204, Sub LCD (1): 0x1ED02A04
|
||||||
u32 lcd_color_addr =
|
u32 lcd_color_addr =
|
||||||
(i == 0) ? LCD_REG_INDEX(color_fill_top) : LCD_REG_INDEX(color_fill_bottom);
|
(fb_id == 0) ? LCD_REG_INDEX(color_fill_top) : LCD_REG_INDEX(color_fill_bottom);
|
||||||
lcd_color_addr = HW::VADDR_LCD + 4 * lcd_color_addr;
|
lcd_color_addr = HW::VADDR_LCD + 4 * lcd_color_addr;
|
||||||
LCD::Regs::ColorFill color_fill = {0};
|
LCD::Regs::ColorFill color_fill = {0};
|
||||||
LCD::Read(color_fill.raw, lcd_color_addr);
|
LCD::Read(color_fill.raw, lcd_color_addr);
|
||||||
|
@ -129,7 +130,7 @@ void RendererOpenGL::SwapBuffers() {
|
||||||
// performance problem.
|
// performance problem.
|
||||||
ConfigureFramebufferTexture(screen_infos[i].texture, framebuffer);
|
ConfigureFramebufferTexture(screen_infos[i].texture, framebuffer);
|
||||||
}
|
}
|
||||||
LoadFBToScreenInfo(framebuffer, screen_infos[i]);
|
LoadFBToScreenInfo(framebuffer, screen_infos[i], i == 1);
|
||||||
|
|
||||||
// Resize the texture in case the framebuffer size has changed
|
// Resize the texture in case the framebuffer size has changed
|
||||||
screen_infos[i].texture.width = framebuffer.width;
|
screen_infos[i].texture.width = framebuffer.width;
|
||||||
|
@ -160,10 +161,15 @@ void RendererOpenGL::SwapBuffers() {
|
||||||
* Loads framebuffer from emulated memory into the active OpenGL texture.
|
* Loads framebuffer from emulated memory into the active OpenGL texture.
|
||||||
*/
|
*/
|
||||||
void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
||||||
ScreenInfo& screen_info) {
|
ScreenInfo& screen_info, bool right_eye) {
|
||||||
|
|
||||||
|
if (framebuffer.address_right1 == 0 || framebuffer.address_right2 == 0)
|
||||||
|
right_eye = false;
|
||||||
|
|
||||||
const PAddr framebuffer_addr =
|
const PAddr framebuffer_addr =
|
||||||
framebuffer.active_fb == 0 ? framebuffer.address_left1 : framebuffer.address_left2;
|
framebuffer.active_fb == 0
|
||||||
|
? (!right_eye ? framebuffer.address_left1 : framebuffer.address_right1)
|
||||||
|
: (!right_eye ? framebuffer.address_left2 : framebuffer.address_right2);
|
||||||
|
|
||||||
LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%08x(%dx%d), fmt %x",
|
LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%08x(%dx%d), fmt %x",
|
||||||
framebuffer.stride * framebuffer.height, framebuffer_addr, (int)framebuffer.width,
|
framebuffer.stride * framebuffer.height, framebuffer_addr, (int)framebuffer.width,
|
||||||
|
@ -395,13 +401,33 @@ void RendererOpenGL::DrawScreens() {
|
||||||
glUniform1i(uniform_color_texture, 0);
|
glUniform1i(uniform_color_texture, 0);
|
||||||
|
|
||||||
if (layout.top_screen_enabled) {
|
if (layout.top_screen_enabled) {
|
||||||
|
if (!Settings::values.toggle_3d) {
|
||||||
DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, (float)top_screen.top,
|
DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, (float)top_screen.top,
|
||||||
(float)top_screen.GetWidth(), (float)top_screen.GetHeight());
|
(float)top_screen.GetWidth(), (float)top_screen.GetHeight());
|
||||||
|
} else {
|
||||||
|
DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2,
|
||||||
|
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
||||||
|
(float)top_screen.GetHeight());
|
||||||
|
DrawSingleScreenRotated(screen_infos[1],
|
||||||
|
((float)top_screen.left / 2) + ((float)layout.width / 2),
|
||||||
|
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
||||||
|
(float)top_screen.GetHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (layout.bottom_screen_enabled) {
|
if (layout.bottom_screen_enabled) {
|
||||||
DrawSingleScreenRotated(screen_infos[1], (float)bottom_screen.left,
|
if (!Settings::values.toggle_3d) {
|
||||||
|
DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left,
|
||||||
(float)bottom_screen.top, (float)bottom_screen.GetWidth(),
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth(),
|
||||||
(float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetHeight());
|
||||||
|
} else {
|
||||||
|
DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left / 2,
|
||||||
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
||||||
|
(float)bottom_screen.GetHeight());
|
||||||
|
DrawSingleScreenRotated(screen_infos[2],
|
||||||
|
((float)bottom_screen.left / 2) + ((float)layout.width / 2),
|
||||||
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
||||||
|
(float)bottom_screen.GetHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_frame++;
|
m_current_frame++;
|
||||||
|
|
|
@ -62,7 +62,7 @@ private:
|
||||||
|
|
||||||
// Loads framebuffer from emulated memory into the display information structure
|
// Loads framebuffer from emulated memory into the display information structure
|
||||||
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
||||||
ScreenInfo& screen_info);
|
ScreenInfo& screen_info, bool right_eye);
|
||||||
// Fills active OpenGL texture with the given RGB color.
|
// Fills active OpenGL texture with the given RGB color.
|
||||||
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ private:
|
||||||
OGLProgram shader;
|
OGLProgram shader;
|
||||||
|
|
||||||
/// Display information for top and bottom screens respectively
|
/// Display information for top and bottom screens respectively
|
||||||
std::array<ScreenInfo, 2> screen_infos;
|
std::array<ScreenInfo, 3> screen_infos;
|
||||||
|
|
||||||
// Shader uniform location indices
|
// Shader uniform location indices
|
||||||
GLuint uniform_modelview_matrix;
|
GLuint uniform_modelview_matrix;
|
||||||
|
|
Loading…
Reference in a new issue