Skip to content
Snippets Groups Projects
Commit 9960c49c authored by bunnei's avatar bunnei
Browse files

Set framebuffer layout from EmuWindow.

parent 8e4e28aa
No related branches found
No related tags found
No related merge requests found
......@@ -36,20 +36,13 @@ const bool EmuWindow_GLFW::IsOpen() {
}
void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) {
ASSERT(width > 0);
ASSERT(height > 0);
GetEmuWindow(win)->NotifyFramebufferSizeChanged(std::pair<unsigned,unsigned>(width, height));
GetEmuWindow(win)->NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height));
}
void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) {
ASSERT(width > 0);
ASSERT(height > 0);
// NOTE: GLFW provides no proper way to set a minimal window size.
// Hence, we just ignore the corresponding EmuWindow hint.
GetEmuWindow(win)->NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(width, height));
OnFramebufferResizeEvent(win, width, height);
}
/// EmuWindow_GLFW constructor
......
......@@ -155,6 +155,7 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
child = new GGLWidgetInternal(fmt, this);
QBoxLayout* layout = new QHBoxLayout(this);
resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
layout->addWidget(child);
layout->setMargin(0);
......@@ -234,7 +235,7 @@ void GRenderWindow::OnFramebufferSizeChanged()
unsigned height = child->QPaintDevice::height();
#endif
NotifyFramebufferSizeChanged(std::make_pair(width, height));
NotifyFramebufferLayoutChanged(EmuWindow::FramebufferLayout::DefaultScreenLayout(width, height));
}
void GRenderWindow::BackupGeometry()
......
......@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "emu_window.h"
#include "video_core/video_core.h"
void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) {
Service::HID::PadState mapped_key = KeyMap::GetPadKey(key);
......@@ -15,3 +16,52 @@ void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) {
Service::HID::PadButtonRelease(mapped_key);
}
EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(int width, int height) {
ASSERT(width > 0);
ASSERT(height > 0);
EmuWindow::FramebufferLayout res = { width, height, {}, {} };
float window_aspect_ratio = static_cast<float>(height) / width;
float emulation_aspect_ratio = static_cast<float>(VideoCore::kScreenTopHeight * 2) /
VideoCore::kScreenTopWidth;
if (window_aspect_ratio > emulation_aspect_ratio) {
// Window is narrower than the emulation content => apply borders to the top and bottom
int viewport_height = static_cast<int>(std::round(emulation_aspect_ratio * width));
res.top_screen.left = 0;
res.top_screen.right = res.top_screen.left + width;
res.top_screen.top = (height - viewport_height) / 2;
res.top_screen.bottom = res.top_screen.top + viewport_height / 2;
int bottom_width = static_cast<int>((static_cast<float>(VideoCore::kScreenBottomWidth) /
VideoCore::kScreenTopWidth) * (res.top_screen.right - res.top_screen.left));
int bottom_border = ((res.top_screen.right - res.top_screen.left) - bottom_width) / 2;
res.bottom_screen.left = bottom_border;
res.bottom_screen.right = res.bottom_screen.left + bottom_width;
res.bottom_screen.top = res.top_screen.bottom;
res.bottom_screen.bottom = res.bottom_screen.top + viewport_height / 2;
} else {
// Otherwise, apply borders to the left and right sides of the window.
int viewport_width = static_cast<int>(std::round(height / emulation_aspect_ratio));
res.top_screen.left = (width - viewport_width) / 2;
res.top_screen.right = res.top_screen.left + viewport_width;
res.top_screen.top = 0;
res.top_screen.bottom = res.top_screen.top + height / 2;
int bottom_width = static_cast<int>((static_cast<float>(VideoCore::kScreenBottomWidth) /
VideoCore::kScreenTopWidth) * (res.top_screen.right - res.top_screen.left));
int bottom_border = ((res.top_screen.right - res.top_screen.left) - bottom_width) / 2;
res.bottom_screen.left = res.top_screen.left + bottom_border;
res.bottom_screen.right = res.bottom_screen.left + bottom_width;
res.bottom_screen.top = res.top_screen.bottom;
res.bottom_screen.bottom = res.bottom_screen.top + height / 2;
}
return res;
}
......@@ -8,6 +8,7 @@
#include "common/scm_rev.h"
#include "common/string_util.h"
#include "common/key_map.h"
#include "common/math_util.h"
/**
* Abstraction class used to provide an interface between emulation code and the frontend
......@@ -38,6 +39,23 @@ public:
std::pair<unsigned,unsigned> min_client_area_size;
};
/// Describes the layout of the window framebuffer (size and top/bottom screen positions)
struct FramebufferLayout {
/**
* Factory method for constructing a default FramebufferLayout
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
static FramebufferLayout DefaultScreenLayout(int width, int height);
unsigned width;
unsigned height;
MathUtil::Rectangle<unsigned> top_screen;
MathUtil::Rectangle<unsigned> bottom_screen;
};
/// Swap buffers to display the next frame
virtual void SwapBuffers() = 0;
......@@ -75,11 +93,11 @@ public:
}
/**
* Gets the framebuffer size in pixels.
* Gets the framebuffer layout (width, height, and screen regions)
* @note This method is thread-safe
*/
const std::pair<unsigned,unsigned> GetFramebufferSize() const {
return framebuffer_size;
const FramebufferLayout& GetFramebufferLayout() const {
return framebuffer_layout;
}
/**
......@@ -118,11 +136,11 @@ protected:
}
/**
* Update internal framebuffer size with the given parameter.
* Update framebuffer layout with the given parameter.
* @note EmuWindow implementations will usually use this in window resize event handlers.
*/
void NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) {
framebuffer_size = size;
void NotifyFramebufferLayoutChanged(const FramebufferLayout& layout) {
framebuffer_layout = layout;
}
/**
......@@ -143,7 +161,7 @@ private:
// By default, ignore this request and do nothing.
}
std::pair<unsigned,unsigned> framebuffer_size;
FramebufferLayout framebuffer_layout; ///< Current framebuffer layout
unsigned client_area_width; ///< Current client width, should be set by window impl.
unsigned client_area_height; ///< Current client height, should be set by window impl.
......
......@@ -242,28 +242,26 @@ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x
* Draws the emulated screens to the emulator window.
*/
void RendererOpenGL::DrawScreens() {
auto viewport_extent = GetViewportExtent();
glViewport(viewport_extent.left, viewport_extent.top, viewport_extent.GetWidth(), viewport_extent.GetHeight()); // TODO: Or bottom?
auto layout = render_window->GetFramebufferLayout();
glViewport(0, 0, layout.width, layout.height);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program_id);
// Set projection matrix
std::array<GLfloat, 3*2> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height);
std::array<GLfloat, 3 * 2> ortho_matrix = MakeOrthographicMatrix((float)layout.width,
(float)layout.height);
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
// Bind texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glUniform1i(uniform_color_texture, 0);
const float max_width = std::max((float)VideoCore::kScreenTopWidth, (float)VideoCore::kScreenBottomWidth);
const float top_x = 0.5f * (max_width - VideoCore::kScreenTopWidth);
const float bottom_x = 0.5f * (max_width - VideoCore::kScreenBottomWidth);
DrawSingleScreenRotated(textures[0], top_x, 0,
(float)VideoCore::kScreenTopWidth, (float)VideoCore::kScreenTopHeight);
DrawSingleScreenRotated(textures[1], bottom_x, (float)VideoCore::kScreenTopHeight,
(float)VideoCore::kScreenBottomWidth, (float)VideoCore::kScreenBottomHeight);
DrawSingleScreenRotated(textures[0], (float)layout.top_screen.left, (float)layout.top_screen.top,
(float)layout.top_screen.GetWidth(), (float)layout.top_screen.GetHeight());
DrawSingleScreenRotated(textures[1], (float)layout.bottom_screen.left,(float)layout.bottom_screen.top,
(float)layout.bottom_screen.GetWidth(), (float)layout.bottom_screen.GetHeight());
m_current_frame++;
}
......@@ -280,34 +278,6 @@ void RendererOpenGL::SetWindow(EmuWindow* window) {
render_window = window;
}
MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() {
unsigned framebuffer_width;
unsigned framebuffer_height;
std::tie(framebuffer_width, framebuffer_height) = render_window->GetFramebufferSize();
float window_aspect_ratio = static_cast<float>(framebuffer_height) / framebuffer_width;
float emulation_aspect_ratio = static_cast<float>(resolution_height) / resolution_width;
MathUtil::Rectangle<unsigned> viewport_extent;
if (window_aspect_ratio > emulation_aspect_ratio) {
// Window is narrower than the emulation content => apply borders to the top and bottom
unsigned viewport_height = static_cast<unsigned>(std::round(emulation_aspect_ratio * framebuffer_width));
viewport_extent.left = 0;
viewport_extent.top = (framebuffer_height - viewport_height) / 2;
viewport_extent.right = viewport_extent.left + framebuffer_width;
viewport_extent.bottom = viewport_extent.top + viewport_height;
} else {
// Otherwise, apply borders to the left and right sides of the window.
unsigned viewport_width = static_cast<unsigned>(std::round(framebuffer_height / emulation_aspect_ratio));
viewport_extent.left = (framebuffer_width - viewport_width) / 2;
viewport_extent.top = 0;
viewport_extent.right = viewport_extent.left + viewport_width;
viewport_extent.bottom = viewport_extent.top + framebuffer_height;
}
return viewport_extent;
}
/// Initialize the renderer
void RendererOpenGL::Init() {
render_window->MakeCurrent();
......
......@@ -18,7 +18,6 @@ namespace VideoCore {
EmuWindow* g_emu_window = nullptr; ///< Frontend emulator window
RendererBase* g_renderer = nullptr; ///< Renderer plugin
int g_current_frame = 0;
/// Initialize the video core
void Init(EmuWindow* emu_window) {
......@@ -27,8 +26,6 @@ void Init(EmuWindow* emu_window) {
g_renderer->SetWindow(g_emu_window);
g_renderer->Init();
g_current_frame = 0;
LOG_DEBUG(Render, "initialized OK");
}
......
......@@ -30,7 +30,6 @@ static const int kScreenBottomHeight = 240; ///< 3DS bottom screen height
// ---------------------
extern RendererBase* g_renderer; ///< Renderer plugin
extern int g_current_frame; ///< Current frame
extern EmuWindow* g_emu_window; ///< Emu window
/// Start the video core
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment