summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt8
-rw-r--r--src/core/hle/service/am/applet_oe.cpp2
-rw-r--r--src/core/hle/service/audio/audio.cpp16
-rw-r--r--src/core/hle/service/audio/audio.h16
-rw-r--r--src/core/hle/service/audio/audout_u.cpp26
-rw-r--r--src/core/hle/service/audio/audout_u.h23
-rw-r--r--src/core/hle/service/hid/hid.cpp61
-rw-r--r--src/core/hle/service/hid/hid.h13
-rw-r--r--src/core/hle/service/lm/lm.cpp2
-rw-r--r--src/core/hle/service/service.cpp12
-rw-r--r--src/core/hle/service/time/time.cpp16
-rw-r--r--src/core/hle/service/time/time.h16
-rw-r--r--src/core/hle/service/time/time_s.cpp58
-rw-r--r--src/core/hle/service/time/time_s.h23
-rw-r--r--src/core/hle/service/vi/vi.cpp5
-rw-r--r--src/video_core/renderer_base.h3
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp32
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h12
18 files changed, 305 insertions, 39 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 021e2f152..f5c92a5aa 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -41,6 +41,8 @@ set(SRCS
41 hle/service/am/applet_oe.cpp 41 hle/service/am/applet_oe.cpp
42 hle/service/aoc/aoc_u.cpp 42 hle/service/aoc/aoc_u.cpp
43 hle/service/apm/apm.cpp 43 hle/service/apm/apm.cpp
44 hle/service/audio/audio.cpp
45 hle/service/audio/audout_u.cpp
44 hle/service/hid/hid.cpp 46 hle/service/hid/hid.cpp
45 hle/service/lm/lm.cpp 47 hle/service/lm/lm.cpp
46 hle/service/nvdrv/devices/nvdisp_disp0.cpp 48 hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -53,6 +55,8 @@ set(SRCS
53 hle/service/service.cpp 55 hle/service/service.cpp
54 hle/service/sm/controller.cpp 56 hle/service/sm/controller.cpp
55 hle/service/sm/sm.cpp 57 hle/service/sm/sm.cpp
58 hle/service/time/time.cpp
59 hle/service/time/time_s.cpp
56 hle/service/vi/vi.cpp 60 hle/service/vi/vi.cpp
57 hle/service/vi/vi_m.cpp 61 hle/service/vi/vi_m.cpp
58 hle/shared_page.cpp 62 hle/shared_page.cpp
@@ -124,6 +128,8 @@ set(HEADERS
124 hle/service/am/applet_oe.h 128 hle/service/am/applet_oe.h
125 hle/service/aoc/aoc_u.h 129 hle/service/aoc/aoc_u.h
126 hle/service/apm/apm.h 130 hle/service/apm/apm.h
131 hle/service/audio/audio.h
132 hle/service/audio/audout_u.h
127 hle/service/hid/hid.h 133 hle/service/hid/hid.h
128 hle/service/lm/lm.h 134 hle/service/lm/lm.h
129 hle/service/nvdrv/devices/nvdevice.h 135 hle/service/nvdrv/devices/nvdevice.h
@@ -137,6 +143,8 @@ set(HEADERS
137 hle/service/service.h 143 hle/service/service.h
138 hle/service/sm/controller.h 144 hle/service/sm/controller.h
139 hle/service/sm/sm.h 145 hle/service/sm/sm.h
146 hle/service/time/time.h
147 hle/service/time/time_s.h
140 hle/service/vi/vi.h 148 hle/service/vi/vi.h
141 hle/service/vi/vi_m.h 149 hle/service/vi/vi_m.h
142 hle/shared_page.h 150 hle/shared_page.h
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index e2bb581ff..f3d66ea96 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -81,7 +81,7 @@ private:
81 void ReceiveMessage(Kernel::HLERequestContext& ctx) { 81 void ReceiveMessage(Kernel::HLERequestContext& ctx) {
82 IPC::RequestBuilder rb{ctx, 3}; 82 IPC::RequestBuilder rb{ctx, 3};
83 rb.Push(RESULT_SUCCESS); 83 rb.Push(RESULT_SUCCESS);
84 rb.Push<u32>(1); 84 rb.Push<u32>(15);
85 85
86 LOG_WARNING(Service, "(STUBBED) called"); 86 LOG_WARNING(Service, "(STUBBED) called");
87 } 87 }
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
new file mode 100644
index 000000000..2b4c6c5d0
--- /dev/null
+++ b/src/core/hle/service/audio/audio.cpp
@@ -0,0 +1,16 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/service/audio/audio.h"
6#include "core/hle/service/audio/audout_u.h"
7
8namespace Service {
9namespace Audio {
10
11void InstallInterfaces(SM::ServiceManager& service_manager) {
12 std::make_shared<AudOutU>()->InstallAsService(service_manager);
13}
14
15} // namespace Audio
16} // namespace Service
diff --git a/src/core/hle/service/audio/audio.h b/src/core/hle/service/audio/audio.h
new file mode 100644
index 000000000..cbd56b2a8
--- /dev/null
+++ b/src/core/hle/service/audio/audio.h
@@ -0,0 +1,16 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9namespace Service {
10namespace Audio {
11
12/// Registers all Audio services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager);
14
15} // namespace Audio
16} // namespace Service
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
new file mode 100644
index 000000000..c028262c6
--- /dev/null
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -0,0 +1,26 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/audio/audout_u.h"
8
9namespace Service {
10namespace Audio {
11
12void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
13 LOG_WARNING(Service, "(STUBBED) called");
14 IPC::RequestBuilder rb{ctx, 2};
15 rb.Push(RESULT_SUCCESS);
16}
17
18AudOutU::AudOutU() : ServiceFramework("audout:u") {
19 static const FunctionInfo functions[] = {
20 {0x00000000, &AudOutU::ListAudioOuts, "ListAudioOuts"},
21 };
22 RegisterHandlers(functions);
23}
24
25} // namespace Audio
26} // namespace Service
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
new file mode 100644
index 000000000..42680af94
--- /dev/null
+++ b/src/core/hle/service/audio/audout_u.h
@@ -0,0 +1,23 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/service.h"
9
10namespace Service {
11namespace Audio {
12
13class AudOutU final : public ServiceFramework<AudOutU> {
14public:
15 AudOutU();
16 ~AudOutU() = default;
17
18private:
19 void ListAudioOuts(Kernel::HLERequestContext& ctx);
20};
21
22} // namespace Audio
23} // namespace Service
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index f838713a3..3f74aed06 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1,19 +1,74 @@
1// Copyright 2015 Citra Emulator Project 1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/client_port.h"
8#include "core/hle/kernel/client_session.h"
9#include "core/hle/kernel/shared_memory.h"
6#include "core/hle/service/hid/hid.h" 10#include "core/hle/service/hid/hid.h"
7#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
8 12
9namespace Service { 13namespace Service {
10namespace HID { 14namespace HID {
11 15
12void Init() {} 16class IAppletResource final : public ServiceFramework<IAppletResource> {
17public:
18 IAppletResource() : ServiceFramework("IAppletResource") {
19 static const FunctionInfo functions[] = {
20 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
21 };
22 RegisterHandlers(functions);
13 23
14void Shutdown() {} 24 shared_mem = Kernel::SharedMemory::Create(
25 nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read,
26 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
27 }
28
29private:
30 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
31 IPC::RequestBuilder rb{ctx, 2, 1};
32 rb.Push(RESULT_SUCCESS);
33 rb.PushCopyObjects(shared_mem);
34 LOG_DEBUG(Service, "called");
35 }
36
37 // Handle to shared memory region designated to HID service
38 Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
39};
40
41class Hid final : public ServiceFramework<Hid> {
42public:
43 Hid() : ServiceFramework("hid") {
44 static const FunctionInfo functions[] = {
45 {0x00000000, &Hid::CreateAppletResource, "CreateAppletResource"},
46 };
47 RegisterHandlers(functions);
48 }
49 ~Hid() = default;
50
51private:
52 void CreateAppletResource(Kernel::HLERequestContext& ctx) {
53 auto client_port = std::make_shared<IAppletResource>()->CreatePort();
54 auto session = client_port->Connect();
55 if (session.Succeeded()) {
56 LOG_DEBUG(Service, "called, initialized IAppletResource -> session=%u",
57 (*session)->GetObjectId());
58 IPC::RequestBuilder rb{ctx, 2, 0, 1};
59 rb.Push(RESULT_SUCCESS);
60 rb.PushMoveObjects(std::move(session).Unwrap());
61 } else {
62 UNIMPLEMENTED();
63 }
64 }
65};
15 66
16void ReloadInputDevices() {} 67void ReloadInputDevices() {}
17 68
69void InstallInterfaces(SM::ServiceManager& service_manager) {
70 std::make_shared<Hid>()->InstallAsService(service_manager);
71}
72
18} // namespace HID 73} // namespace HID
19} // namespace Service 74} // namespace Service
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index a1d227dfe..f7621f62d 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -1,20 +1,19 @@
1// Copyright 2015 Citra Emulator Project 1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/service.h"
8
7namespace Service { 9namespace Service {
8namespace HID { 10namespace HID {
9 11
10/// Initialize HID service
11void Init();
12
13/// Shutdown HID service
14void Shutdown();
15
16/// Reload input devices. Used when input configuration changed 12/// Reload input devices. Used when input configuration changed
17void ReloadInputDevices(); 13void ReloadInputDevices();
18 14
15/// Registers all HID services with the specified service manager.
16void InstallInterfaces(SM::ServiceManager& service_manager);
17
19} // namespace HID 18} // namespace HID
20} // namespace Service 19} // namespace Service
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index ca429e15f..2d0d2fb65 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -144,7 +144,7 @@ void LM::Initialize(Kernel::HLERequestContext& ctx) {
144 if (session.Succeeded()) { 144 if (session.Succeeded()) {
145 LOG_DEBUG(Service_SM, "called, initialized logger -> session=%u", 145 LOG_DEBUG(Service_SM, "called, initialized logger -> session=%u",
146 (*session)->GetObjectId()); 146 (*session)->GetObjectId());
147 IPC::RequestBuilder rb{ctx, 1, 0, 1}; 147 IPC::RequestBuilder rb{ctx, 2, 0, 1};
148 rb.Push(RESULT_SUCCESS); 148 rb.Push(RESULT_SUCCESS);
149 rb.PushMoveObjects(std::move(session).Unwrap()); 149 rb.PushMoveObjects(std::move(session).Unwrap());
150 registered_loggers.emplace_back(std::move(client_port)); 150 registered_loggers.emplace_back(std::move(client_port));
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index b82df6f35..02d434660 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -17,6 +17,7 @@
17#include "core/hle/service/am/am.h" 17#include "core/hle/service/am/am.h"
18#include "core/hle/service/aoc/aoc_u.h" 18#include "core/hle/service/aoc/aoc_u.h"
19#include "core/hle/service/apm/apm.h" 19#include "core/hle/service/apm/apm.h"
20#include "core/hle/service/audio/audio.h"
20#include "core/hle/service/hid/hid.h" 21#include "core/hle/service/hid/hid.h"
21#include "core/hle/service/lm/lm.h" 22#include "core/hle/service/lm/lm.h"
22#include "core/hle/service/nvdrv/nvdrv.h" 23#include "core/hle/service/nvdrv/nvdrv.h"
@@ -24,6 +25,7 @@
24#include "core/hle/service/service.h" 25#include "core/hle/service/service.h"
25#include "core/hle/service/sm/controller.h" 26#include "core/hle/service/sm/controller.h"
26#include "core/hle/service/sm/sm.h" 27#include "core/hle/service/sm/sm.h"
28#include "core/hle/service/time/time.h"
27#include "core/hle/service/vi/vi.h" 29#include "core/hle/service/vi/vi.h"
28 30
29using Kernel::ClientPort; 31using Kernel::ClientPort;
@@ -78,7 +80,8 @@ Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {
78 ASSERT(port == nullptr); 80 ASSERT(port == nullptr);
79 Kernel::SharedPtr<Kernel::ServerPort> server_port; 81 Kernel::SharedPtr<Kernel::ServerPort> server_port;
80 Kernel::SharedPtr<Kernel::ClientPort> client_port; 82 Kernel::SharedPtr<Kernel::ClientPort> client_port;
81 std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, service_name); 83 std::tie(server_port, client_port) =
84 Kernel::ServerPort::CreatePortPair(max_sessions, service_name);
82 port = MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)).Unwrap(); 85 port = MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)).Unwrap();
83 port->SetHleHandler(shared_from_this()); 86 port->SetHleHandler(shared_from_this());
84 return client_port; 87 return client_port;
@@ -164,20 +167,19 @@ void Init() {
164 AM::InstallInterfaces(*SM::g_service_manager); 167 AM::InstallInterfaces(*SM::g_service_manager);
165 AOC::InstallInterfaces(*SM::g_service_manager); 168 AOC::InstallInterfaces(*SM::g_service_manager);
166 APM::InstallInterfaces(*SM::g_service_manager); 169 APM::InstallInterfaces(*SM::g_service_manager);
170 Audio::InstallInterfaces(*SM::g_service_manager);
171 HID::InstallInterfaces(*SM::g_service_manager);
167 LM::InstallInterfaces(*SM::g_service_manager); 172 LM::InstallInterfaces(*SM::g_service_manager);
168 NVDRV::InstallInterfaces(*SM::g_service_manager); 173 NVDRV::InstallInterfaces(*SM::g_service_manager);
169 PCTL::InstallInterfaces(*SM::g_service_manager); 174 PCTL::InstallInterfaces(*SM::g_service_manager);
175 Time::InstallInterfaces(*SM::g_service_manager);
170 VI::InstallInterfaces(*SM::g_service_manager); 176 VI::InstallInterfaces(*SM::g_service_manager);
171 177
172 HID::Init();
173
174 LOG_DEBUG(Service, "initialized OK"); 178 LOG_DEBUG(Service, "initialized OK");
175} 179}
176 180
177/// Shutdown ServiceManager 181/// Shutdown ServiceManager
178void Shutdown() { 182void Shutdown() {
179 HID::Shutdown();
180
181 SM::g_service_manager = nullptr; 183 SM::g_service_manager = nullptr;
182 g_kernel_named_ports.clear(); 184 g_kernel_named_ports.clear();
183 LOG_DEBUG(Service, "shutdown OK"); 185 LOG_DEBUG(Service, "shutdown OK");
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
new file mode 100644
index 000000000..e3d58aa60
--- /dev/null
+++ b/src/core/hle/service/time/time.cpp
@@ -0,0 +1,16 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/service/time/time.h"
6#include "core/hle/service/time/time_s.h"
7
8namespace Service {
9namespace Time {
10
11void InstallInterfaces(SM::ServiceManager& service_manager) {
12 std::make_shared<TimeS>()->InstallAsService(service_manager);
13}
14
15} // namespace Time
16} // namespace Service
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
new file mode 100644
index 000000000..7d0803e24
--- /dev/null
+++ b/src/core/hle/service/time/time.h
@@ -0,0 +1,16 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9namespace Service {
10namespace Time {
11
12/// Registers all Time services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager);
14
15} // namespace Time
16} // namespace Service
diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp
new file mode 100644
index 000000000..6b0597d8e
--- /dev/null
+++ b/src/core/hle/service/time/time_s.cpp
@@ -0,0 +1,58 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <chrono>
6#include "common/logging/log.h"
7#include "core/hle/ipc_helpers.h"
8#include "core/hle/kernel/client_port.h"
9#include "core/hle/kernel/client_session.h"
10#include "core/hle/service/time/time_s.h"
11
12namespace Service {
13namespace Time {
14
15class ISystemClock final : public ServiceFramework<ISystemClock> {
16public:
17 ISystemClock() : ServiceFramework("ISystemClock") {
18 static const FunctionInfo functions[] = {
19 {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
20 };
21 RegisterHandlers(functions);
22 }
23
24private:
25 void GetCurrentTime(Kernel::HLERequestContext& ctx) {
26 const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::milliseconds>(
27 std::chrono::system_clock::now().time_since_epoch())
28 .count()};
29 IPC::RequestBuilder rb{ctx, 4};
30 rb.Push(RESULT_SUCCESS);
31 rb.Push<u64>(time_since_epoch);
32 LOG_DEBUG(Service, "called");
33 }
34};
35
36void TimeS::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
37 auto client_port = std::make_shared<ISystemClock>()->CreatePort();
38 auto session = client_port->Connect();
39 if (session.Succeeded()) {
40 LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u",
41 (*session)->GetObjectId());
42 IPC::RequestBuilder rb{ctx, 2, 0, 1};
43 rb.Push(RESULT_SUCCESS);
44 rb.PushMoveObjects(std::move(session).Unwrap());
45 } else {
46 UNIMPLEMENTED();
47 }
48}
49
50TimeS::TimeS() : ServiceFramework("time:s") {
51 static const FunctionInfo functions[] = {
52 {0x00000000, &TimeS::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
53 };
54 RegisterHandlers(functions);
55}
56
57} // namespace Time
58} // namespace Service
diff --git a/src/core/hle/service/time/time_s.h b/src/core/hle/service/time/time_s.h
new file mode 100644
index 000000000..073227910
--- /dev/null
+++ b/src/core/hle/service/time/time_s.h
@@ -0,0 +1,23 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/service.h"
9
10namespace Service {
11namespace Time {
12
13class TimeS final : public ServiceFramework<TimeS> {
14public:
15 TimeS();
16 ~TimeS() = default;
17
18private:
19 void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
20};
21
22} // namespace Time
23} // namespace Service
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index d3b63949e..b35a7a377 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -12,6 +12,8 @@
12#include "core/hle/service/nvdrv/nvdrv_a.h" 12#include "core/hle/service/nvdrv/nvdrv_a.h"
13#include "core/hle/service/vi/vi.h" 13#include "core/hle/service/vi/vi.h"
14#include "core/hle/service/vi/vi_m.h" 14#include "core/hle/service/vi/vi_m.h"
15#include "video_core/renderer_base.h"
16#include "video_core/video_core.h"
15 17
16namespace Service { 18namespace Service {
17namespace VI { 19namespace VI {
@@ -743,7 +745,8 @@ void NVFlinger::Compose() {
743 auto buffer = buffer_queue->AcquireBuffer(); 745 auto buffer = buffer_queue->AcquireBuffer();
744 746
745 if (buffer == boost::none) { 747 if (buffer == boost::none) {
746 // There was no queued buffer to draw. 748 // There was no queued buffer to draw, render previous frame
749 VideoCore::g_renderer->SwapBuffers({});
747 continue; 750 continue;
748 } 751 }
749 752
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index d15db6c8c..28893b181 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <boost/optional.hpp>
8#include "common/assert.h" 9#include "common/assert.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10 11
@@ -47,7 +48,7 @@ public:
47 virtual ~RendererBase() {} 48 virtual ~RendererBase() {}
48 49
49 /// Swap buffers (render frame) 50 /// Swap buffers (render frame)
50 virtual void SwapBuffers(const FramebufferInfo& framebuffer_info) = 0; 51 virtual void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) = 0;
51 52
52 /** 53 /**
53 * Set the emulator window to use for renderer 54 * Set the emulator window to use for renderer
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index a5df91604..50396b5c1 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -4,8 +4,8 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cstddef> 6#include <cstddef>
7#include <cstring>
8#include <cstdlib> 7#include <cstdlib>
8#include <cstring>
9#include <memory> 9#include <memory>
10#include <glad/glad.h> 10#include <glad/glad.h>
11#include "common/assert.h" 11#include "common/assert.h"
@@ -98,20 +98,23 @@ RendererOpenGL::RendererOpenGL() = default;
98RendererOpenGL::~RendererOpenGL() = default; 98RendererOpenGL::~RendererOpenGL() = default;
99 99
100/// Swap buffers (render frame) 100/// Swap buffers (render frame)
101void RendererOpenGL::SwapBuffers(const FramebufferInfo& framebuffer_info) { 101void RendererOpenGL::SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) {
102 // Maintain the rasterizer's state as a priority 102 // Maintain the rasterizer's state as a priority
103 OpenGLState prev_state = OpenGLState::GetCurState(); 103 OpenGLState prev_state = OpenGLState::GetCurState();
104 state.Apply(); 104 state.Apply();
105 105
106 if (screen_info.texture.width != (GLsizei)framebuffer_info.width || 106 if (framebuffer_info != boost::none) {
107 screen_info.texture.height != (GLsizei)framebuffer_info.height || 107 // If framebuffer_info is provided, reload it from memory to a texture
108 screen_info.texture.pixel_format != framebuffer_info.pixel_format) { 108 if (screen_info.texture.width != (GLsizei)framebuffer_info->width ||
109 // Reallocate texture if the framebuffer size has changed. 109 screen_info.texture.height != (GLsizei)framebuffer_info->height ||
110 // This is expected to not happen very often and hence should not be a 110 screen_info.texture.pixel_format != framebuffer_info->pixel_format) {
111 // performance problem. 111 // Reallocate texture if the framebuffer size has changed.
112 ConfigureFramebufferTexture(screen_info.texture, framebuffer_info); 112 // This is expected to not happen very often and hence should not be a
113 // performance problem.
114 ConfigureFramebufferTexture(screen_info.texture, *framebuffer_info);
115 }
116 LoadFBToScreenInfo(*framebuffer_info, screen_info);
113 } 117 }
114 LoadFBToScreenInfo(framebuffer_info, screen_info);
115 118
116 DrawScreens(); 119 DrawScreens();
117 120
@@ -290,16 +293,16 @@ void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info,
290 * Fills active OpenGL texture with the given RGB color. Since the color is solid, the texture can 293 * Fills active OpenGL texture with the given RGB color. Since the color is solid, the texture can
291 * be 1x1 but will stretch across whatever it's rendered on. 294 * be 1x1 but will stretch across whatever it's rendered on.
292 */ 295 */
293void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, 296void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
294 const TextureInfo& texture) { 297 const TextureInfo& texture) {
295 state.texture_units[0].texture_2d = texture.resource.handle; 298 state.texture_units[0].texture_2d = texture.resource.handle;
296 state.Apply(); 299 state.Apply();
297 300
298 glActiveTexture(GL_TEXTURE0); 301 glActiveTexture(GL_TEXTURE0);
299 u8 framebuffer_data[3] = {color_r, color_g, color_b}; 302 u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
300 303
301 // Update existing texture 304 // Update existing texture
302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, framebuffer_data); 305 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
303 306
304 state.texture_units[0].texture_2d = 0; 307 state.texture_units[0].texture_2d = 0;
305 state.Apply(); 308 state.Apply();
@@ -361,6 +364,9 @@ void RendererOpenGL::InitOpenGLObjects() {
361 364
362 state.texture_units[0].texture_2d = 0; 365 state.texture_units[0].texture_2d = 0;
363 state.Apply(); 366 state.Apply();
367
368 // Clear screen to black
369 LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
364} 370}
365 371
366void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, 372void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index dc21d7a38..dd01e1b1a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -37,7 +37,7 @@ public:
37 ~RendererOpenGL() override; 37 ~RendererOpenGL() override;
38 38
39 /// Swap buffers (render frame) 39 /// Swap buffers (render frame)
40 void SwapBuffers(const FramebufferInfo& framebuffer_info) override; 40 void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) override;
41 41
42 /** 42 /**
43 * Set the emulator window to use for renderer 43 * Set the emulator window to use for renderer
@@ -53,17 +53,15 @@ public:
53 53
54private: 54private:
55 void InitOpenGLObjects(); 55 void InitOpenGLObjects();
56 void ConfigureFramebufferTexture(TextureInfo& texture, 56 void ConfigureFramebufferTexture(TextureInfo& texture, const FramebufferInfo& framebuffer_info);
57 const FramebufferInfo& framebuffer_info);
58 void DrawScreens(); 57 void DrawScreens();
59 void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); 58 void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
60 void UpdateFramerate(); 59 void UpdateFramerate();
61 60
62 // Loads framebuffer from emulated memory into the display information structure 61 // Loads framebuffer from emulated memory into the display information structure
63 void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, 62 void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info);
64 ScreenInfo& screen_info); 63 // Fills active OpenGL texture with the given RGBA color.
65 // Fills active OpenGL texture with the given RGB color. 64 void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture);
66 void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
67 65
68 EmuWindow* render_window; ///< Handle to render window 66 EmuWindow* render_window; ///< Handle to render window
69 67