diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index 8ecc1b202..690534d22 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -281,7 +281,7 @@ int main(int argc, char** argv) {
 
     SCOPE_EXIT({ system.Shutdown(); });
 
-    const Core::System::ResultStatus load_result{system.Load(emu_window.get(), filepath)};
+    const Core::System::ResultStatus load_result{system.Load(*emu_window, filepath)};
 
     switch (load_result) {
     case Core::System::ResultStatus::ErrorGetLoader:
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 2b6e96f95..c71d96506 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -642,7 +642,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
 
     Core::System& system{Core::System::GetInstance()};
 
-    const Core::System::ResultStatus result{system.Load(render_window, filename.toStdString())};
+    const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
 
     if (result != Core::System::ResultStatus::Success) {
         switch (result) {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 8f84174e4..894f8e21a 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -83,7 +83,7 @@ System::ResultStatus System::SingleStep() {
     return RunLoop(false);
 }
 
-System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
+System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& filepath) {
     app_loader = Loader::GetLoader(filepath);
 
     if (!app_loader) {
@@ -152,7 +152,7 @@ void System::Reschedule() {
     Kernel::Reschedule();
 }
 
-System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
+System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) {
     LOG_DEBUG(HW_Memory, "initialized OK");
 
     CoreTiming::Init();
diff --git a/src/core/core.h b/src/core/core.h
index ff5d5934b..5c55659a4 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -81,11 +81,12 @@ public:
 
     /**
      * Load an executable application.
-     * @param emu_window Pointer to the host-system window used for video output and keyboard input.
+     * @param emu_window Reference to the host-system window used for video output and keyboard
+     *                   input.
      * @param filepath String path to the executable application to load on the host file system.
      * @returns ResultStatus code, indicating if the operation succeeded.
      */
-    ResultStatus Load(EmuWindow* emu_window, const std::string& filepath);
+    ResultStatus Load(EmuWindow& emu_window, const std::string& filepath);
 
     /**
      * Indicates if the emulated system is powered on (all subsystems initialized and able to run an
@@ -166,11 +167,12 @@ public:
 private:
     /**
      * Initialize the emulated system.
-     * @param emu_window Pointer to the host-system window used for video output and keyboard input.
+     * @param emu_window Reference to the host-system window used for video output and keyboard
+     *                   input.
      * @param system_mode The system mode.
      * @return ResultStatus code, indicating if the operation succeeded.
      */
-    ResultStatus Init(EmuWindow* emu_window, u32 system_mode);
+    ResultStatus Init(EmuWindow& emu_window, u32 system_mode);
 
     /// Reschedule the core emulation
     void Reschedule();
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 551849b20..c648714fb 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -4,11 +4,11 @@
 
 #include "audio_core/dsp_interface.h"
 #include "core/core.h"
-#include "core/frontend/emu_window.h"
 #include "core/gdbstub/gdbstub.h"
 #include "core/hle/service/hid/hid.h"
 #include "core/hle/service/ir/ir.h"
 #include "core/settings.h"
+#include "video_core/renderer_base.h"
 #include "video_core/video_core.h"
 
 namespace Settings {
@@ -26,9 +26,8 @@ void Apply() {
     VideoCore::g_hw_shader_accurate_gs = values.shaders_accurate_gs;
     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul;
 
-    if (VideoCore::g_emu_window) {
-        auto layout = VideoCore::g_emu_window->GetFramebufferLayout();
-        VideoCore::g_emu_window->UpdateCurrentFramebufferLayout(layout.width, layout.height);
+    if (VideoCore::g_renderer) {
+        VideoCore::g_renderer->UpdateCurrentFramebufferLayout();
     }
 
     VideoCore::g_renderer_bg_color_update_requested = true;
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index f6ece5c4b..a35ee7ad8 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -2,20 +2,27 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <atomic>
 #include <memory>
+#include "core/frontend/emu_window.h"
 #include "video_core/renderer_base.h"
 #include "video_core/renderer_opengl/gl_rasterizer.h"
 #include "video_core/swrasterizer/swrasterizer.h"
 #include "video_core/video_core.h"
 
+RendererBase::RendererBase(EmuWindow& window) : render_window{window} {}
+RendererBase::~RendererBase() = default;
+void RendererBase::UpdateCurrentFramebufferLayout() {
+    const Layout::FramebufferLayout& layout = render_window.GetFramebufferLayout();
+    render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
+}
+
 void RendererBase::RefreshRasterizerSetting() {
     bool hw_renderer_enabled = VideoCore::g_hw_renderer_enabled;
     if (rasterizer == nullptr || opengl_rasterizer_active != hw_renderer_enabled) {
         opengl_rasterizer_active = hw_renderer_enabled;
 
         if (hw_renderer_enabled) {
-            rasterizer = std::make_unique<RasterizerOpenGL>();
+            rasterizer = std::make_unique<RasterizerOpenGL>(render_window);
         } else {
             rasterizer = std::make_unique<VideoCore::SWRasterizer>();
         }
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 8bc545dd0..ff9a71aba 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -16,23 +16,21 @@ public:
     /// Used to reference a framebuffer
     enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture };
 
-    virtual ~RendererBase() {}
+    explicit RendererBase(EmuWindow& window);
+    virtual ~RendererBase();
 
     /// Swap buffers (render frame)
     virtual void SwapBuffers() = 0;
 
-    /**
-     * Set the emulator window to use for renderer
-     * @param window EmuWindow handle to emulator window to use for rendering
-     */
-    virtual void SetWindow(EmuWindow* window) = 0;
-
     /// Initialize the renderer
     virtual Core::System::ResultStatus Init() = 0;
 
     /// Shutdown the renderer
     virtual void ShutDown() = 0;
 
+    /// Updates the framebuffer layout of the contained render window handle.
+    void UpdateCurrentFramebufferLayout();
+
     // Getter/setter functions:
     // ------------------------
 
@@ -48,9 +46,14 @@ public:
         return rasterizer.get();
     }
 
+    EmuWindow& GetRenderWindow() const {
+        return render_window;
+    }
+
     void RefreshRasterizerSetting();
 
 protected:
+    EmuWindow& render_window; ///< Reference to the render window handle.
     std::unique_ptr<VideoCore::RasterizerInterface> rasterizer;
     f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
     int m_current_frame = 0;  ///< Current frame, should be set by the renderer
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 04ca9cffc..1aab999e2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -40,12 +40,12 @@ static bool IsVendorAmd() {
     return gpu_vendor == "ATI Technologies Inc." || gpu_vendor == "Advanced Micro Devices, Inc.";
 }
 
-RasterizerOpenGL::RasterizerOpenGL()
+RasterizerOpenGL::RasterizerOpenGL(EmuWindow& window)
     : is_amd(IsVendorAmd()), shader_dirty(true),
       vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd),
       uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false),
       index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false),
-      texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) {
+      texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false), emu_window{window} {
 
     allow_shadow = GLAD_GL_ARB_shader_image_load_store && GLAD_GL_ARB_shader_image_size &&
                    GLAD_GL_ARB_framebuffer_no_attachments;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 216a7b76c..b116a33cf 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -29,12 +29,13 @@
 #include "video_core/renderer_opengl/pica_to_gl.h"
 #include "video_core/shader/shader.h"
 
+class EmuWindow;
 struct ScreenInfo;
 class ShaderProgramManager;
 
 class RasterizerOpenGL : public VideoCore::RasterizerInterface {
 public:
-    RasterizerOpenGL();
+    explicit RasterizerOpenGL(EmuWindow& renderer);
     ~RasterizerOpenGL() override;
 
     void AddTriangle(const Pica::Shader::OutputVertex& v0, const Pica::Shader::OutputVertex& v1,
@@ -249,6 +250,8 @@ private:
 
     RasterizerCacheOpenGL res_cache;
 
+    EmuWindow& emu_window;
+
     std::vector<HardwareVertex> vertex_batch;
 
     bool shader_dirty;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 7ac52394d..9ca9532af 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -26,6 +26,7 @@
 #include "core/memory.h"
 #include "core/settings.h"
 #include "video_core/pica_state.h"
+#include "video_core/renderer_base.h"
 #include "video_core/renderer_opengl/gl_rasterizer_cache.h"
 #include "video_core/renderer_opengl/gl_state.h"
 #include "video_core/utils.h"
@@ -77,7 +78,7 @@ constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
 
 static u16 GetResolutionScaleFactor() {
     return !Settings::values.resolution_factor
-               ? VideoCore::g_emu_window->GetFramebufferLayout().GetScalingRatio()
+               ? VideoCore::g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio()
                : Settings::values.resolution_factor;
 }
 
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 73e7e0178..89ed057c0 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -94,7 +94,7 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
     return matrix;
 }
 
-RendererOpenGL::RendererOpenGL() = default;
+RendererOpenGL::RendererOpenGL(EmuWindow& window) : RendererBase{window} {}
 RendererOpenGL::~RendererOpenGL() = default;
 
 /// Swap buffers (render frame)
@@ -143,8 +143,8 @@ void RendererOpenGL::SwapBuffers() {
     Core::System::GetInstance().perf_stats.EndSystemFrame();
 
     // Swap buffers
-    render_window->PollEvents();
-    render_window->SwapBuffers();
+    render_window.PollEvents();
+    render_window.SwapBuffers();
 
     Core::System::GetInstance().frame_limiter.DoFrameLimiting(CoreTiming::GetGlobalTimeUs());
     Core::System::GetInstance().perf_stats.BeginSystemFrame();
@@ -390,7 +390,7 @@ void RendererOpenGL::DrawScreens() {
                      0.0f);
     }
 
-    auto layout = render_window->GetFramebufferLayout();
+    auto layout = render_window.GetFramebufferLayout();
     const auto& top_screen = layout.top_screen;
     const auto& bottom_screen = layout.bottom_screen;
 
@@ -442,14 +442,6 @@ void RendererOpenGL::DrawScreens() {
 /// Updates the framerate
 void RendererOpenGL::UpdateFramerate() {}
 
-/**
- * Set the emulator window to use for renderer
- * @param window EmuWindow handle to emulator window to use for rendering
- */
-void RendererOpenGL::SetWindow(EmuWindow* window) {
-    render_window = window;
-}
-
 static const char* GetSource(GLenum source) {
 #define RET(s)                                                                                     \
     case GL_DEBUG_SOURCE_##s:                                                                      \
@@ -506,7 +498,7 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum
 
 /// Initialize the renderer
 Core::System::ResultStatus RendererOpenGL::Init() {
-    render_window->MakeCurrent();
+    render_window.MakeCurrent();
 
     if (GLAD_GL_KHR_debug) {
         glEnable(GL_DEBUG_OUTPUT);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index c391e4967..47cc9aaa9 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -34,18 +34,12 @@ struct ScreenInfo {
 
 class RendererOpenGL : public RendererBase {
 public:
-    RendererOpenGL();
+    explicit RendererOpenGL(EmuWindow& window);
     ~RendererOpenGL() override;
 
     /// Swap buffers (render frame)
     void SwapBuffers() override;
 
-    /**
-     * Set the emulator window to use for renderer
-     * @param window EmuWindow handle to emulator window to use for rendering
-     */
-    void SetWindow(EmuWindow* window) override;
-
     /// Initialize the renderer
     Core::System::ResultStatus Init() override;
 
@@ -66,8 +60,6 @@ private:
     // Fills active OpenGL texture with the given RGB color.
     void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
 
-    EmuWindow* render_window; ///< Handle to render window
-
     OpenGLState state;
 
     // OpenGL object IDs
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index a3b565dc9..4c39c0b52 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -14,7 +14,6 @@
 
 namespace VideoCore {
 
-EmuWindow* g_emu_window = nullptr;        ///< Frontend emulator window
 std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
 
 std::atomic<bool> g_hw_renderer_enabled;
@@ -25,12 +24,10 @@ std::atomic<bool> g_hw_shader_accurate_mul;
 std::atomic<bool> g_renderer_bg_color_update_requested;
 
 /// Initialize the video core
-Core::System::ResultStatus Init(EmuWindow* emu_window) {
+Core::System::ResultStatus Init(EmuWindow& emu_window) {
     Pica::Init();
 
-    g_emu_window = emu_window;
-    g_renderer = std::make_unique<RendererOpenGL>();
-    g_renderer->SetWindow(g_emu_window);
+    g_renderer = std::make_unique<RendererOpenGL>(emu_window);
     Core::System::ResultStatus result = g_renderer->Init();
 
     if (result != Core::System::ResultStatus::Success) {
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h
index 605ded59e..deee7a7a7 100644
--- a/src/video_core/video_core.h
+++ b/src/video_core/video_core.h
@@ -17,7 +17,6 @@ class RendererBase;
 namespace VideoCore {
 
 extern std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
-extern EmuWindow* g_emu_window;                  ///< Emu window
 
 // TODO: Wrap these in a user settings struct along with any other graphics settings (often set from
 // qt ui)
@@ -29,7 +28,7 @@ extern std::atomic<bool> g_hw_shader_accurate_mul;
 extern std::atomic<bool> g_renderer_bg_color_update_requested;
 
 /// Initialize the video core
-Core::System::ResultStatus Init(EmuWindow* emu_window);
+Core::System::ResultStatus Init(EmuWindow& emu_window);
 
 /// Shutdown the video core
 void Shutdown();