mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-11-04 12:34:39 +08:00 
			
		
		
		
	Fixup EmuWindow interface and implementations thereof.
This commit is contained in:
		
							parent
							
								
									221a9b023d
								
							
						
					
					
						commit
						bd8f491e4c
					
				@ -2,6 +2,8 @@
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <GLFW/glfw3.h>
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
 | 
			
		||||
#include "video_core/video_core.h"
 | 
			
		||||
@ -10,22 +12,21 @@
 | 
			
		||||
 | 
			
		||||
#include "citra/emu_window/emu_window_glfw.h"
 | 
			
		||||
 | 
			
		||||
EmuWindow_GLFW* EmuWindow_GLFW::GetEmuWindow(GLFWwindow* win) {
 | 
			
		||||
    return static_cast<EmuWindow_GLFW*>(glfwGetWindowUserPointer(win));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Called by GLFW when a key event occurs
 | 
			
		||||
void EmuWindow_GLFW::OnKeyEvent(GLFWwindow* win, int key, int scancode, int action, int mods) {
 | 
			
		||||
 | 
			
		||||
    if (!VideoCore::g_emu_window) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int keyboard_id = ((EmuWindow_GLFW*)VideoCore::g_emu_window)->keyboard_id;
 | 
			
		||||
    int keyboard_id = GetEmuWindow(win)->keyboard_id;
 | 
			
		||||
 | 
			
		||||
    if (action == GLFW_PRESS) {
 | 
			
		||||
        EmuWindow::KeyPressed({key, keyboard_id});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (action == GLFW_RELEASE) {
 | 
			
		||||
    } else if (action == GLFW_RELEASE) {
 | 
			
		||||
        EmuWindow::KeyReleased({key, keyboard_id});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HID_User::PadUpdateComplete();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,8 +35,18 @@ const bool EmuWindow_GLFW::IsOpen() {
 | 
			
		||||
    return glfwWindowShouldClose(m_render_window) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmuWindow_GLFW::GetFramebufferSize(int* fbWidth, int* fbHeight) {
 | 
			
		||||
    glfwGetFramebufferSize(m_render_window, fbWidth, fbHeight);
 | 
			
		||||
void EmuWindow_GLFW::OnFramebufferResizeEvent(GLFWwindow* win, int width, int height) {
 | 
			
		||||
    _dbg_assert_(GUI, width > 0);
 | 
			
		||||
    _dbg_assert_(GUI, height > 0);
 | 
			
		||||
 | 
			
		||||
    GetEmuWindow(win)->NotifyFramebufferSizeChanged(std::pair<unsigned,unsigned>(width, height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) {
 | 
			
		||||
    _dbg_assert_(GUI, width > 0);
 | 
			
		||||
    _dbg_assert_(GUI, height > 0);
 | 
			
		||||
 | 
			
		||||
    GetEmuWindow(win)->NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(width, height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// EmuWindow_GLFW constructor
 | 
			
		||||
@ -54,20 +65,30 @@ EmuWindow_GLFW::EmuWindow_GLFW() {
 | 
			
		||||
    // GLFW on OSX requires these window hints to be set to create a 3.2+ GL context.
 | 
			
		||||
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
 | 
			
		||||
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
    m_render_window = glfwCreateWindow(VideoCore::kScreenTopWidth, 
 | 
			
		||||
        (VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight), 
 | 
			
		||||
        m_window_title.c_str(), NULL, NULL);
 | 
			
		||||
        GetWindowTitle().c_str(), NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    if (m_render_window == NULL) {
 | 
			
		||||
        printf("Failed to create GLFW window! Exiting...");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Setup callbacks
 | 
			
		||||
    glfwSetWindowUserPointer(m_render_window, this);
 | 
			
		||||
    glfwSetKeyCallback(m_render_window, OnKeyEvent);
 | 
			
		||||
 | 
			
		||||
    glfwSetWindowUserPointer(m_render_window, this);
 | 
			
		||||
 | 
			
		||||
    // Notify base interface about window state
 | 
			
		||||
    int width, height;
 | 
			
		||||
    glfwGetFramebufferSize(m_render_window, &width, &height);
 | 
			
		||||
    OnFramebufferResizeEvent(m_render_window, width, height);
 | 
			
		||||
 | 
			
		||||
    glfwGetWindowSize(m_render_window, &width, &height);
 | 
			
		||||
    OnClientAreaResizeEvent(m_render_window, width, height);
 | 
			
		||||
 | 
			
		||||
    // Setup callbacks
 | 
			
		||||
    glfwSetKeyCallback(m_render_window, OnKeyEvent);
 | 
			
		||||
    glfwSetFramebufferSizeCallback(m_render_window, OnFramebufferResizeEvent);
 | 
			
		||||
    glfwSetWindowSizeCallback(m_render_window, OnClientAreaResizeEvent);
 | 
			
		||||
 | 
			
		||||
    DoneCurrent();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,10 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <GLFW/glfw3.h>
 | 
			
		||||
 | 
			
		||||
#include "common/emu_window.h"
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
class EmuWindow_GLFW : public EmuWindow {
 | 
			
		||||
public:
 | 
			
		||||
    EmuWindow_GLFW();
 | 
			
		||||
@ -30,12 +30,15 @@ public:
 | 
			
		||||
    /// Whether the window is still open, and a close request hasn't yet been sent
 | 
			
		||||
    const bool IsOpen();
 | 
			
		||||
 | 
			
		||||
    static void OnClientAreaResizeEvent(GLFWwindow* win, int width, int height);
 | 
			
		||||
 | 
			
		||||
    static void OnFramebufferResizeEvent(GLFWwindow* win, int width, int height);
 | 
			
		||||
 | 
			
		||||
    void ReloadSetKeymaps() override;
 | 
			
		||||
 | 
			
		||||
    /// Gets the size of the window in pixels
 | 
			
		||||
    void GetFramebufferSize(int* fbWidth, int* fbHeight);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static EmuWindow_GLFW* GetEmuWindow(GLFWwindow* win);
 | 
			
		||||
 | 
			
		||||
    GLFWwindow* m_render_window; ///< Internal GLFW render window
 | 
			
		||||
 | 
			
		||||
    /// Device id of keyboard for use with KeyMap
 | 
			
		||||
 | 
			
		||||
@ -88,20 +88,20 @@ void EmuThread::Stop()
 | 
			
		||||
class GGLWidgetInternal : public QGLWidget
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) : QGLWidget(fmt, parent)
 | 
			
		||||
    {
 | 
			
		||||
        parent_ = parent;
 | 
			
		||||
    GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent)
 | 
			
		||||
                     : QGLWidget(fmt, parent), parent(parent) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void paintEvent(QPaintEvent* ev) override
 | 
			
		||||
    {
 | 
			
		||||
    void paintEvent(QPaintEvent* ev) override {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void resizeEvent(QResizeEvent* ev) override {
 | 
			
		||||
        parent_->SetClientAreaWidth(size().width());
 | 
			
		||||
        parent_->SetClientAreaHeight(size().height());
 | 
			
		||||
        parent->OnClientAreaResized(ev->size().width(), ev->size().height());
 | 
			
		||||
        parent->OnFramebufferSizeChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    GRenderWindow* parent_;
 | 
			
		||||
    GRenderWindow* parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EmuThread& GRenderWindow::GetEmuThread()
 | 
			
		||||
@ -120,16 +120,23 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
 | 
			
		||||
    fmt.setProfile(QGLFormat::CoreProfile);
 | 
			
		||||
    // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X
 | 
			
		||||
    fmt.setOption(QGL::NoDeprecatedFunctions);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    child = new GGLWidgetInternal(fmt, this);
 | 
			
		||||
    QBoxLayout* layout = new QHBoxLayout(this);
 | 
			
		||||
    resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
 | 
			
		||||
    layout->addWidget(child);
 | 
			
		||||
    layout->setMargin(0);
 | 
			
		||||
    setLayout(layout);
 | 
			
		||||
    QObject::connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
 | 
			
		||||
    connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
 | 
			
		||||
 | 
			
		||||
    OnFramebufferSizeChanged();
 | 
			
		||||
    NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(child->width(), child->height()));
 | 
			
		||||
 | 
			
		||||
    BackupGeometry();
 | 
			
		||||
 | 
			
		||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
 | 
			
		||||
    connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged()));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GRenderWindow::moveContext()
 | 
			
		||||
@ -182,22 +189,26 @@ void GRenderWindow::PollEvents() {
 | 
			
		||||
    */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// On Qt 5.1+, this correctly gets the size of the framebuffer (pixels).
 | 
			
		||||
// On Qt 5.0+, this correctly gets the size of the framebuffer (pixels).
 | 
			
		||||
//
 | 
			
		||||
// Older versions get the window size (density independent pixels),
 | 
			
		||||
// and hence, do not support DPI scaling ("retina" displays).
 | 
			
		||||
// The result will be a viewport that is smaller than the extent of the window.
 | 
			
		||||
void GRenderWindow::GetFramebufferSize(int* fbWidth, int* fbHeight)
 | 
			
		||||
void GRenderWindow::OnFramebufferSizeChanged()
 | 
			
		||||
{
 | 
			
		||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
 | 
			
		||||
    int pixelRatio = child->QPaintDevice::devicePixelRatio();
 | 
			
		||||
    
 | 
			
		||||
    *fbWidth = child->QPaintDevice::width() * pixelRatio;
 | 
			
		||||
    *fbHeight = child->QPaintDevice::height() * pixelRatio;
 | 
			
		||||
    // Screen changes potentially incur a change in screen DPI, hence we should update the framebuffer size
 | 
			
		||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
 | 
			
		||||
    // windowHandle() might not be accessible until the window is displayed to screen.
 | 
			
		||||
    auto pixel_ratio = windowHandle() ? (windowHandle()->screen()->devicePixelRatio()) : 1.0;
 | 
			
		||||
 | 
			
		||||
    unsigned width = child->QPaintDevice::width() * pixel_ratio;
 | 
			
		||||
    unsigned height = child->QPaintDevice::height() * pixel_ratio;
 | 
			
		||||
#else
 | 
			
		||||
    *fbWidth = child->QPaintDevice::width();
 | 
			
		||||
    *fbHeight = child->QPaintDevice::height();
 | 
			
		||||
    unsigned width = child->QPaintDevice::width();
 | 
			
		||||
    unsigned height = child->QPaintDevice::height();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    NotifyFramebufferSizeChanged(std::make_pair(width, height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GRenderWindow::BackupGeometry()
 | 
			
		||||
@ -260,3 +271,7 @@ void GRenderWindow::ReloadSetKeymaps()
 | 
			
		||||
    KeyMap::SetKeyMapping({Settings::values.pad_sdown_key,  keyboard_id}, HID_User::PAD_CIRCLE_DOWN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height)
 | 
			
		||||
{
 | 
			
		||||
    NotifyClientAreaSizeChanged(std::make_pair(width, height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,16 @@
 | 
			
		||||
#include <atomic>
 | 
			
		||||
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QGLWidget>
 | 
			
		||||
#include <atomic>
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
#include "common/emu_window.h"
 | 
			
		||||
 | 
			
		||||
class GRenderWindow;
 | 
			
		||||
class QScreen;
 | 
			
		||||
class QKeyEvent;
 | 
			
		||||
 | 
			
		||||
class GRenderWindow;
 | 
			
		||||
 | 
			
		||||
class EmuThread : public QThread
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
@ -74,7 +78,7 @@ private:
 | 
			
		||||
signals:
 | 
			
		||||
    /**
 | 
			
		||||
     * Emitted when CPU when we've finished processing a single Gekko instruction
 | 
			
		||||
     * 
 | 
			
		||||
     *
 | 
			
		||||
     * @warning This will only be emitted when the CPU is not running (SetCpuRunning(false))
 | 
			
		||||
     * @warning When connecting to this signal from other threads, make sure to specify either Qt::QueuedConnection (invoke slot within the destination object's message thread) or even Qt::BlockingQueuedConnection (additionally block source thread until slot returns)
 | 
			
		||||
     */
 | 
			
		||||
@ -96,12 +100,11 @@ public:
 | 
			
		||||
    void MakeCurrent() override;
 | 
			
		||||
    void DoneCurrent() override;
 | 
			
		||||
    void PollEvents() override;
 | 
			
		||||
    void GetFramebufferSize(int* fbWidth, int* fbHeight) override;
 | 
			
		||||
 | 
			
		||||
    void BackupGeometry();
 | 
			
		||||
    void RestoreGeometry();
 | 
			
		||||
    void restoreGeometry(const QByteArray& geometry); // overridden
 | 
			
		||||
    QByteArray saveGeometry(); // overridden
 | 
			
		||||
    QByteArray saveGeometry();  // overridden
 | 
			
		||||
 | 
			
		||||
    EmuThread& GetEmuThread();
 | 
			
		||||
 | 
			
		||||
@ -110,8 +113,12 @@ public:
 | 
			
		||||
 | 
			
		||||
    void ReloadSetKeymaps() override;
 | 
			
		||||
 | 
			
		||||
    void OnClientAreaResized(unsigned width, unsigned height);
 | 
			
		||||
 | 
			
		||||
    void OnFramebufferSizeChanged();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void moveContext();
 | 
			
		||||
    void moveContext();  // overridden
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QGLWidget* child;
 | 
			
		||||
 | 
			
		||||
@ -43,54 +43,59 @@ public:
 | 
			
		||||
    static void KeyReleased(KeyMap::HostDeviceKey key);
 | 
			
		||||
 | 
			
		||||
    WindowConfig GetConfig() const {
 | 
			
		||||
        return m_config;
 | 
			
		||||
        return config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetConfig(const WindowConfig& val) {
 | 
			
		||||
        m_config = val;
 | 
			
		||||
        config = val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets the size of the window in pixels
 | 
			
		||||
    virtual void GetFramebufferSize(int* fbWidth, int* fbHeight) = 0;
 | 
			
		||||
 | 
			
		||||
    int GetClientAreaWidth() const {
 | 
			
		||||
        return m_client_area_width;
 | 
			
		||||
    /**
 | 
			
		||||
      * Gets the size of the framebuffer in pixels
 | 
			
		||||
      */
 | 
			
		||||
    const std::pair<unsigned,unsigned> GetFramebufferSize() const {
 | 
			
		||||
        return framebuffer_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetClientAreaWidth(const int val) {
 | 
			
		||||
        m_client_area_width = val;
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets window client area width in logical coordinates
 | 
			
		||||
     */
 | 
			
		||||
    std::pair<unsigned,unsigned> GetClientAreaSize() const {
 | 
			
		||||
        return std::make_pair(client_area_width, client_area_height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int GetClientAreaHeight() const {
 | 
			
		||||
        return m_client_area_height;
 | 
			
		||||
    std::string GetWindowTitle() const {
 | 
			
		||||
        return window_title;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetClientAreaHeight(const int val) {
 | 
			
		||||
        m_client_area_height = val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string GetWindowTitle() const { 
 | 
			
		||||
        return m_window_title;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void SetWindowTitle(std::string val) {
 | 
			
		||||
        m_window_title = val;
 | 
			
		||||
    void SetWindowTitle(const std::string& val) {
 | 
			
		||||
        window_title = val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    EmuWindow():
 | 
			
		||||
        m_window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc)),
 | 
			
		||||
    EmuWindow() : // TODO: What the hell... -.- - don't hardcode dimensions here without applying them in a sensible manner...
 | 
			
		||||
        window_title(Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc))
 | 
			
		||||
        m_client_area_width(640),
 | 
			
		||||
        m_client_area_height(480)
 | 
			
		||||
        m_client_area_height(480),
 | 
			
		||||
    {}
 | 
			
		||||
    virtual ~EmuWindow() {}
 | 
			
		||||
 | 
			
		||||
    std::string m_window_title;     ///< Current window title, should be used by window impl.
 | 
			
		||||
    std::pair<unsigned,unsigned> NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) {
 | 
			
		||||
        framebuffer_size = size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int m_client_area_width;        ///< Current client width, should be set by window impl.
 | 
			
		||||
    int m_client_area_height;       ///< Current client height, should be set by window impl.
 | 
			
		||||
    void NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned> size) {
 | 
			
		||||
        client_area_width = size.first;
 | 
			
		||||
        client_area_height = size.second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    WindowConfig m_config;                ///< Internal configuration
 | 
			
		||||
    std::string window_title;      ///< Current window title, should be used by window impl.
 | 
			
		||||
 | 
			
		||||
    std::pair<unsigned,unsigned> framebuffer_size;
 | 
			
		||||
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
    WindowConfig config;         ///< Internal configuration
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -230,10 +230,10 @@ void RendererOpenGL::SetWindow(EmuWindow* window) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RendererOpenGL::UpdateViewportExtent() {
 | 
			
		||||
    int width_in_pixels;
 | 
			
		||||
    int height_in_pixels;
 | 
			
		||||
    unsigned width_in_pixels;
 | 
			
		||||
    unsigned height_in_pixels;
 | 
			
		||||
 | 
			
		||||
    render_window->GetFramebufferSize(&width_in_pixels, &height_in_pixels);
 | 
			
		||||
    std::tie(width_in_pixels, height_in_pixels) = render_window->GetFramebufferSize();
 | 
			
		||||
 | 
			
		||||
    // No update needed if framebuffer size hasn't changed
 | 
			
		||||
    if (width_in_pixels == framebuffer_size.width && height_in_pixels == framebuffer_size.height) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user