diff options
Diffstat (limited to 'src')
23 files changed, 418 insertions, 75 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 52f253d1e..041267318 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -257,7 +257,7 @@ void Process::Acquire(Thread* thread) { | |||
| 257 | ASSERT_MSG(!ShouldWait(thread), "Object unavailable!"); | 257 | ASSERT_MSG(!ShouldWait(thread), "Object unavailable!"); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | bool Process::ShouldWait(Thread* thread) const { | 260 | bool Process::ShouldWait(const Thread* thread) const { |
| 261 | return !is_signaled; | 261 | return !is_signaled; |
| 262 | } | 262 | } |
| 263 | 263 | ||
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index f9ddc937c..f060f2a3b 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -251,7 +251,7 @@ private: | |||
| 251 | ~Process() override; | 251 | ~Process() override; |
| 252 | 252 | ||
| 253 | /// Checks if the specified thread should wait until this process is available. | 253 | /// Checks if the specified thread should wait until this process is available. |
| 254 | bool ShouldWait(Thread* thread) const override; | 254 | bool ShouldWait(const Thread* thread) const override; |
| 255 | 255 | ||
| 256 | /// Acquires/locks this process for the specified thread if it's available. | 256 | /// Acquires/locks this process for the specified thread if it's available. |
| 257 | void Acquire(Thread* thread) override; | 257 | void Acquire(Thread* thread) override; |
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index 0e5083f70..c2b798a4e 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp | |||
| @@ -14,7 +14,7 @@ namespace Kernel { | |||
| 14 | ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {} | 14 | ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {} |
| 15 | ReadableEvent::~ReadableEvent() = default; | 15 | ReadableEvent::~ReadableEvent() = default; |
| 16 | 16 | ||
| 17 | bool ReadableEvent::ShouldWait(Thread* thread) const { | 17 | bool ReadableEvent::ShouldWait(const Thread* thread) const { |
| 18 | return !signaled; | 18 | return !signaled; |
| 19 | } | 19 | } |
| 20 | 20 | ||
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h index 77a9c362c..2eb9dcbb7 100644 --- a/src/core/hle/kernel/readable_event.h +++ b/src/core/hle/kernel/readable_event.h | |||
| @@ -36,7 +36,7 @@ public: | |||
| 36 | return HANDLE_TYPE; | 36 | return HANDLE_TYPE; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | bool ShouldWait(Thread* thread) const override; | 39 | bool ShouldWait(const Thread* thread) const override; |
| 40 | void Acquire(Thread* thread) override; | 40 | void Acquire(Thread* thread) override; |
| 41 | 41 | ||
| 42 | /// Unconditionally clears the readable event's state. | 42 | /// Unconditionally clears the readable event's state. |
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index 0e1515c89..708fdf9e1 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp | |||
| @@ -30,7 +30,7 @@ void ServerPort::AppendPendingSession(SharedPtr<ServerSession> pending_session) | |||
| 30 | pending_sessions.push_back(std::move(pending_session)); | 30 | pending_sessions.push_back(std::move(pending_session)); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | bool ServerPort::ShouldWait(Thread* thread) const { | 33 | bool ServerPort::ShouldWait(const Thread* thread) const { |
| 34 | // If there are no pending sessions, we wait until a new one is added. | 34 | // If there are no pending sessions, we wait until a new one is added. |
| 35 | return pending_sessions.empty(); | 35 | return pending_sessions.empty(); |
| 36 | } | 36 | } |
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index 9bc667cf2..76293cb8b 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h | |||
| @@ -75,7 +75,7 @@ public: | |||
| 75 | /// waiting to be accepted by this port. | 75 | /// waiting to be accepted by this port. |
| 76 | void AppendPendingSession(SharedPtr<ServerSession> pending_session); | 76 | void AppendPendingSession(SharedPtr<ServerSession> pending_session); |
| 77 | 77 | ||
| 78 | bool ShouldWait(Thread* thread) const override; | 78 | bool ShouldWait(const Thread* thread) const override; |
| 79 | void Acquire(Thread* thread) override; | 79 | void Acquire(Thread* thread) override; |
| 80 | 80 | ||
| 81 | private: | 81 | private: |
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 4d8a337a7..40cec143e 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -46,7 +46,7 @@ ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelCore& kernel, st | |||
| 46 | return MakeResult(std::move(server_session)); | 46 | return MakeResult(std::move(server_session)); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | bool ServerSession::ShouldWait(Thread* thread) const { | 49 | bool ServerSession::ShouldWait(const Thread* thread) const { |
| 50 | // Closed sessions should never wait, an error will be returned from svcReplyAndReceive. | 50 | // Closed sessions should never wait, an error will be returned from svcReplyAndReceive. |
| 51 | if (parent->client == nullptr) | 51 | if (parent->client == nullptr) |
| 52 | return false; | 52 | return false; |
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index aea4ccfeb..79b84bade 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h | |||
| @@ -82,7 +82,7 @@ public: | |||
| 82 | */ | 82 | */ |
| 83 | ResultCode HandleSyncRequest(SharedPtr<Thread> thread); | 83 | ResultCode HandleSyncRequest(SharedPtr<Thread> thread); |
| 84 | 84 | ||
| 85 | bool ShouldWait(Thread* thread) const override; | 85 | bool ShouldWait(const Thread* thread) const override; |
| 86 | 86 | ||
| 87 | void Acquire(Thread* thread) override; | 87 | void Acquire(Thread* thread) override; |
| 88 | 88 | ||
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 62861da36..f15c5ee36 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include "core/hle/kernel/errors.h" | 9 | #include "core/hle/kernel/errors.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/shared_memory.h" | 11 | #include "core/hle/kernel/shared_memory.h" |
| 12 | #include "core/memory.h" | ||
| 13 | 12 | ||
| 14 | namespace Kernel { | 13 | namespace Kernel { |
| 15 | 14 | ||
| @@ -119,7 +118,15 @@ ResultCode SharedMemory::Map(Process& target_process, VAddr address, MemoryPermi | |||
| 119 | ConvertPermissions(permissions)); | 118 | ConvertPermissions(permissions)); |
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | ResultCode SharedMemory::Unmap(Process& target_process, VAddr address) { | 121 | ResultCode SharedMemory::Unmap(Process& target_process, VAddr address, u64 unmap_size) { |
| 122 | if (unmap_size != size) { | ||
| 123 | LOG_ERROR(Kernel, | ||
| 124 | "Invalid size passed to Unmap. Size must be equal to the size of the " | ||
| 125 | "memory managed. Shared memory size=0x{:016X}, Unmap size=0x{:016X}", | ||
| 126 | size, unmap_size); | ||
| 127 | return ERR_INVALID_SIZE; | ||
| 128 | } | ||
| 129 | |||
| 123 | // TODO(Subv): Verify what happens if the application tries to unmap an address that is not | 130 | // TODO(Subv): Verify what happens if the application tries to unmap an address that is not |
| 124 | // mapped to a SharedMemory. | 131 | // mapped to a SharedMemory. |
| 125 | return target_process.VMManager().UnmapRange(address, size); | 132 | return target_process.VMManager().UnmapRange(address, size); |
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index dab2a6bea..37e18c443 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h | |||
| @@ -104,11 +104,17 @@ public: | |||
| 104 | 104 | ||
| 105 | /** | 105 | /** |
| 106 | * Unmaps a shared memory block from the specified address in system memory | 106 | * Unmaps a shared memory block from the specified address in system memory |
| 107 | * | ||
| 107 | * @param target_process Process from which to unmap the memory block. | 108 | * @param target_process Process from which to unmap the memory block. |
| 108 | * @param address Address in system memory where the shared memory block is mapped | 109 | * @param address Address in system memory where the shared memory block is mapped. |
| 110 | * @param unmap_size The amount of bytes to unmap from this shared memory instance. | ||
| 111 | * | ||
| 109 | * @return Result code of the unmap operation | 112 | * @return Result code of the unmap operation |
| 113 | * | ||
| 114 | * @pre The given size to unmap must be the same size as the amount of memory managed by | ||
| 115 | * the SharedMemory instance itself, otherwise ERR_INVALID_SIZE will be returned. | ||
| 110 | */ | 116 | */ |
| 111 | ResultCode Unmap(Process& target_process, VAddr address); | 117 | ResultCode Unmap(Process& target_process, VAddr address, u64 unmap_size); |
| 112 | 118 | ||
| 113 | /** | 119 | /** |
| 114 | * Gets a pointer to the shared memory block | 120 | * Gets a pointer to the shared memory block |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 23c768f57..ab10db3df 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1140,7 +1140,7 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 | |||
| 1140 | return ERR_INVALID_MEMORY_RANGE; | 1140 | return ERR_INVALID_MEMORY_RANGE; |
| 1141 | } | 1141 | } |
| 1142 | 1142 | ||
| 1143 | return shared_memory->Unmap(*current_process, addr); | 1143 | return shared_memory->Unmap(*current_process, addr, size); |
| 1144 | } | 1144 | } |
| 1145 | 1145 | ||
| 1146 | static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_address, | 1146 | static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_address, |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 3ec3710b2..1b891f632 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | namespace Kernel { | 29 | namespace Kernel { |
| 30 | 30 | ||
| 31 | bool Thread::ShouldWait(Thread* thread) const { | 31 | bool Thread::ShouldWait(const Thread* thread) const { |
| 32 | return status != ThreadStatus::Dead; | 32 | return status != ThreadStatus::Dead; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| @@ -233,16 +233,16 @@ void Thread::SetWaitSynchronizationOutput(s32 output) { | |||
| 233 | context.cpu_registers[1] = output; | 233 | context.cpu_registers[1] = output; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | s32 Thread::GetWaitObjectIndex(WaitObject* object) const { | 236 | s32 Thread::GetWaitObjectIndex(const WaitObject* object) const { |
| 237 | ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); | 237 | ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); |
| 238 | auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); | 238 | const auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); |
| 239 | return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); | 239 | return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | VAddr Thread::GetCommandBufferAddress() const { | 242 | VAddr Thread::GetCommandBufferAddress() const { |
| 243 | // Offset from the start of TLS at which the IPC command buffer begins. | 243 | // Offset from the start of TLS at which the IPC command buffer begins. |
| 244 | static constexpr int CommandHeaderOffset = 0x80; | 244 | constexpr u64 command_header_offset = 0x80; |
| 245 | return GetTLSAddress() + CommandHeaderOffset; | 245 | return GetTLSAddress() + command_header_offset; |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | void Thread::SetStatus(ThreadStatus new_status) { | 248 | void Thread::SetStatus(ThreadStatus new_status) { |
| @@ -371,7 +371,7 @@ void Thread::ChangeScheduler() { | |||
| 371 | system.CpuCore(processor_id).PrepareReschedule(); | 371 | system.CpuCore(processor_id).PrepareReschedule(); |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | bool Thread::AllWaitObjectsReady() { | 374 | bool Thread::AllWaitObjectsReady() const { |
| 375 | return std::none_of( | 375 | return std::none_of( |
| 376 | wait_objects.begin(), wait_objects.end(), | 376 | wait_objects.begin(), wait_objects.end(), |
| 377 | [this](const SharedPtr<WaitObject>& object) { return object->ShouldWait(this); }); | 377 | [this](const SharedPtr<WaitObject>& object) { return object->ShouldWait(this); }); |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 9c684758c..73e5d1bb4 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -111,7 +111,7 @@ public: | |||
| 111 | return HANDLE_TYPE; | 111 | return HANDLE_TYPE; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | bool ShouldWait(Thread* thread) const override; | 114 | bool ShouldWait(const Thread* thread) const override; |
| 115 | void Acquire(Thread* thread) override; | 115 | void Acquire(Thread* thread) override; |
| 116 | 116 | ||
| 117 | /** | 117 | /** |
| @@ -205,7 +205,7 @@ public: | |||
| 205 | * object in the list. | 205 | * object in the list. |
| 206 | * @param object Object to query the index of. | 206 | * @param object Object to query the index of. |
| 207 | */ | 207 | */ |
| 208 | s32 GetWaitObjectIndex(WaitObject* object) const; | 208 | s32 GetWaitObjectIndex(const WaitObject* object) const; |
| 209 | 209 | ||
| 210 | /** | 210 | /** |
| 211 | * Stops a thread, invalidating it from further use | 211 | * Stops a thread, invalidating it from further use |
| @@ -299,7 +299,7 @@ public: | |||
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | /// Determines whether all the objects this thread is waiting on are ready. | 301 | /// Determines whether all the objects this thread is waiting on are ready. |
| 302 | bool AllWaitObjectsReady(); | 302 | bool AllWaitObjectsReady() const; |
| 303 | 303 | ||
| 304 | const MutexWaitingThreads& GetMutexWaitingThreads() const { | 304 | const MutexWaitingThreads& GetMutexWaitingThreads() const { |
| 305 | return wait_mutex_threads; | 305 | return wait_mutex_threads; |
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h index 5987fb971..04464a51a 100644 --- a/src/core/hle/kernel/wait_object.h +++ b/src/core/hle/kernel/wait_object.h | |||
| @@ -24,7 +24,7 @@ public: | |||
| 24 | * @param thread The thread about which we're deciding. | 24 | * @param thread The thread about which we're deciding. |
| 25 | * @return True if the current thread should wait due to this object being unavailable | 25 | * @return True if the current thread should wait due to this object being unavailable |
| 26 | */ | 26 | */ |
| 27 | virtual bool ShouldWait(Thread* thread) const = 0; | 27 | virtual bool ShouldWait(const Thread* thread) const = 0; |
| 28 | 28 | ||
| 29 | /// Acquire/lock the object for the specified thread if it is available | 29 | /// Acquire/lock the object for the specified thread if it is available |
| 30 | virtual void Acquire(Thread* thread) = 0; | 30 | virtual void Acquire(Thread* thread) = 0; |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9c44e27c6..d31ab7970 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -239,8 +239,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger | |||
| 239 | {0, nullptr, "Exit"}, | 239 | {0, nullptr, "Exit"}, |
| 240 | {1, &ISelfController::LockExit, "LockExit"}, | 240 | {1, &ISelfController::LockExit, "LockExit"}, |
| 241 | {2, &ISelfController::UnlockExit, "UnlockExit"}, | 241 | {2, &ISelfController::UnlockExit, "UnlockExit"}, |
| 242 | {3, nullptr, "EnterFatalSection"}, | 242 | {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, |
| 243 | {4, nullptr, "LeaveFatalSection"}, | 243 | {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, |
| 244 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, | 244 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, |
| 245 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, | 245 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, |
| 246 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, | 246 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, |
| @@ -285,41 +285,54 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger | |||
| 285 | 285 | ||
| 286 | ISelfController::~ISelfController() = default; | 286 | ISelfController::~ISelfController() = default; |
| 287 | 287 | ||
| 288 | void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { | 288 | void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { |
| 289 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 290 | // u8, these are bool flags. No output. | ||
| 291 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 289 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 292 | 290 | ||
| 293 | IPC::RequestParser rp{ctx}; | 291 | IPC::ResponseBuilder rb{ctx, 2}; |
| 292 | rb.Push(RESULT_SUCCESS); | ||
| 293 | } | ||
| 294 | 294 | ||
| 295 | struct FocusHandlingModeParams { | 295 | void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { |
| 296 | u8 unknown0; | 296 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 297 | u8 unknown1; | ||
| 298 | u8 unknown2; | ||
| 299 | }; | ||
| 300 | auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 301 | 297 | ||
| 302 | IPC::ResponseBuilder rb{ctx, 2}; | 298 | IPC::ResponseBuilder rb{ctx, 2}; |
| 303 | rb.Push(RESULT_SUCCESS); | 299 | rb.Push(RESULT_SUCCESS); |
| 304 | } | 300 | } |
| 305 | 301 | ||
| 306 | void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { | 302 | void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) { |
| 307 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 303 | ++num_fatal_sections_entered; |
| 304 | LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); | ||
| 308 | 305 | ||
| 309 | IPC::ResponseBuilder rb{ctx, 2}; | 306 | IPC::ResponseBuilder rb{ctx, 2}; |
| 310 | rb.Push(RESULT_SUCCESS); | 307 | rb.Push(RESULT_SUCCESS); |
| 311 | } | 308 | } |
| 312 | 309 | ||
| 313 | void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { | 310 | void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) { |
| 314 | IPC::RequestParser rp{ctx}; | 311 | LOG_DEBUG(Service_AM, "called."); |
| 315 | 312 | ||
| 316 | bool flag = rp.Pop<bool>(); | 313 | // Entry and exit of fatal sections must be balanced. |
| 317 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | 314 | if (num_fatal_sections_entered == 0) { |
| 315 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 316 | rb.Push(ResultCode{ErrorModule::AM, 512}); | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | --num_fatal_sections_entered; | ||
| 318 | 321 | ||
| 319 | IPC::ResponseBuilder rb{ctx, 2}; | 322 | IPC::ResponseBuilder rb{ctx, 2}; |
| 320 | rb.Push(RESULT_SUCCESS); | 323 | rb.Push(RESULT_SUCCESS); |
| 321 | } | 324 | } |
| 322 | 325 | ||
| 326 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { | ||
| 327 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 328 | |||
| 329 | launchable_event.writable->Signal(); | ||
| 330 | |||
| 331 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 332 | rb.Push(RESULT_SUCCESS); | ||
| 333 | rb.PushCopyObjects(launchable_event.readable); | ||
| 334 | } | ||
| 335 | |||
| 323 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { | 336 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { |
| 324 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 337 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 325 | 338 | ||
| @@ -337,40 +350,51 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont | |||
| 337 | rb.Push(RESULT_SUCCESS); | 350 | rb.Push(RESULT_SUCCESS); |
| 338 | } | 351 | } |
| 339 | 352 | ||
| 340 | void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { | 353 | void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { |
| 341 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 342 | // u8, these are bool flags. No output. | ||
| 343 | IPC::RequestParser rp{ctx}; | 354 | IPC::RequestParser rp{ctx}; |
| 344 | 355 | ||
| 345 | bool enabled = rp.Pop<bool>(); | 356 | bool flag = rp.Pop<bool>(); |
| 346 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | 357 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); |
| 347 | 358 | ||
| 348 | IPC::ResponseBuilder rb{ctx, 2}; | 359 | IPC::ResponseBuilder rb{ctx, 2}; |
| 349 | rb.Push(RESULT_SUCCESS); | 360 | rb.Push(RESULT_SUCCESS); |
| 350 | } | 361 | } |
| 351 | 362 | ||
| 352 | void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { | 363 | void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { |
| 364 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 365 | // u8, these are bool flags. No output. | ||
| 353 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 366 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 354 | 367 | ||
| 368 | IPC::RequestParser rp{ctx}; | ||
| 369 | |||
| 370 | struct FocusHandlingModeParams { | ||
| 371 | u8 unknown0; | ||
| 372 | u8 unknown1; | ||
| 373 | u8 unknown2; | ||
| 374 | }; | ||
| 375 | auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 376 | |||
| 355 | IPC::ResponseBuilder rb{ctx, 2}; | 377 | IPC::ResponseBuilder rb{ctx, 2}; |
| 356 | rb.Push(RESULT_SUCCESS); | 378 | rb.Push(RESULT_SUCCESS); |
| 357 | } | 379 | } |
| 358 | 380 | ||
| 359 | void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { | 381 | void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { |
| 360 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 382 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 361 | 383 | ||
| 362 | IPC::ResponseBuilder rb{ctx, 2}; | 384 | IPC::ResponseBuilder rb{ctx, 2}; |
| 363 | rb.Push(RESULT_SUCCESS); | 385 | rb.Push(RESULT_SUCCESS); |
| 364 | } | 386 | } |
| 365 | 387 | ||
| 366 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { | 388 | void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { |
| 367 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 389 | // Takes 3 input u8s with each field located immediately after the previous |
| 390 | // u8, these are bool flags. No output. | ||
| 391 | IPC::RequestParser rp{ctx}; | ||
| 368 | 392 | ||
| 369 | launchable_event.writable->Signal(); | 393 | bool enabled = rp.Pop<bool>(); |
| 394 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | ||
| 370 | 395 | ||
| 371 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 396 | IPC::ResponseBuilder rb{ctx, 2}; |
| 372 | rb.Push(RESULT_SUCCESS); | 397 | rb.Push(RESULT_SUCCESS); |
| 373 | rb.PushCopyObjects(launchable_event.readable); | ||
| 374 | } | 398 | } |
| 375 | 399 | ||
| 376 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { | 400 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 565dd8e9e..991b7d47c 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -117,17 +117,19 @@ public: | |||
| 117 | ~ISelfController() override; | 117 | ~ISelfController() override; |
| 118 | 118 | ||
| 119 | private: | 119 | private: |
| 120 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); | ||
| 121 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); | ||
| 122 | void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 123 | void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 124 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); | ||
| 125 | void LockExit(Kernel::HLERequestContext& ctx); | 120 | void LockExit(Kernel::HLERequestContext& ctx); |
| 126 | void UnlockExit(Kernel::HLERequestContext& ctx); | 121 | void UnlockExit(Kernel::HLERequestContext& ctx); |
| 122 | void EnterFatalSection(Kernel::HLERequestContext& ctx); | ||
| 123 | void LeaveFatalSection(Kernel::HLERequestContext& ctx); | ||
| 127 | void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); | 124 | void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); |
| 125 | void SetScreenShotPermission(Kernel::HLERequestContext& ctx); | ||
| 126 | void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 127 | void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 128 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); | ||
| 129 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); | ||
| 130 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); | ||
| 128 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); | 131 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); |
| 129 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); | 132 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); |
| 130 | void SetScreenShotPermission(Kernel::HLERequestContext& ctx); | ||
| 131 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); | 133 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); |
| 132 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 134 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
| 133 | void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 135 | void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
| @@ -135,6 +137,7 @@ private: | |||
| 135 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 137 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 136 | Kernel::EventPair launchable_event; | 138 | Kernel::EventPair launchable_event; |
| 137 | u32 idle_time_detection_extension = 0; | 139 | u32 idle_time_detection_extension = 0; |
| 140 | u64 num_fatal_sections_entered = 0; | ||
| 138 | }; | 141 | }; |
| 139 | 142 | ||
| 140 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 143 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 14b76680f..44c761d3e 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -128,7 +128,9 @@ if (ENABLE_VULKAN) | |||
| 128 | renderer_vulkan/vk_scheduler.cpp | 128 | renderer_vulkan/vk_scheduler.cpp |
| 129 | renderer_vulkan/vk_scheduler.h | 129 | renderer_vulkan/vk_scheduler.h |
| 130 | renderer_vulkan/vk_stream_buffer.cpp | 130 | renderer_vulkan/vk_stream_buffer.cpp |
| 131 | renderer_vulkan/vk_stream_buffer.h) | 131 | renderer_vulkan/vk_stream_buffer.h |
| 132 | renderer_vulkan/vk_swapchain.cpp | ||
| 133 | renderer_vulkan/vk_swapchain.h) | ||
| 132 | 134 | ||
| 133 | target_include_directories(video_core PRIVATE ../../externals/Vulkan-Headers/include) | 135 | target_include_directories(video_core PRIVATE ../../externals/Vulkan-Headers/include) |
| 134 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) | 136 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp new file mode 100644 index 000000000..08279e562 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <array> | ||
| 7 | #include <limits> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/assert.h" | ||
| 11 | #include "common/logging/log.h" | ||
| 12 | #include "core/core.h" | ||
| 13 | #include "core/frontend/framebuffer_layout.h" | ||
| 14 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 15 | #include "video_core/renderer_vulkan/vk_device.h" | ||
| 16 | #include "video_core/renderer_vulkan/vk_resource_manager.h" | ||
| 17 | #include "video_core/renderer_vulkan/vk_swapchain.h" | ||
| 18 | |||
| 19 | namespace Vulkan { | ||
| 20 | |||
| 21 | namespace { | ||
| 22 | vk::SurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& formats) { | ||
| 23 | if (formats.size() == 1 && formats[0].format == vk::Format::eUndefined) { | ||
| 24 | return {vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear}; | ||
| 25 | } | ||
| 26 | const auto& found = std::find_if(formats.begin(), formats.end(), [](const auto& format) { | ||
| 27 | return format.format == vk::Format::eB8G8R8A8Unorm && | ||
| 28 | format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear; | ||
| 29 | }); | ||
| 30 | return found != formats.end() ? *found : formats[0]; | ||
| 31 | } | ||
| 32 | |||
| 33 | vk::PresentModeKHR ChooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& modes) { | ||
| 34 | // Mailbox doesn't lock the application like fifo (vsync), prefer it | ||
| 35 | const auto& found = std::find_if(modes.begin(), modes.end(), [](const auto& mode) { | ||
| 36 | return mode == vk::PresentModeKHR::eMailbox; | ||
| 37 | }); | ||
| 38 | return found != modes.end() ? *found : vk::PresentModeKHR::eFifo; | ||
| 39 | } | ||
| 40 | |||
| 41 | vk::Extent2D ChooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, | ||
| 42 | u32 height) { | ||
| 43 | constexpr auto undefined_size{std::numeric_limits<u32>::max()}; | ||
| 44 | if (capabilities.currentExtent.width != undefined_size) { | ||
| 45 | return capabilities.currentExtent; | ||
| 46 | } | ||
| 47 | vk::Extent2D extent = {width, height}; | ||
| 48 | extent.width = std::max(capabilities.minImageExtent.width, | ||
| 49 | std::min(capabilities.maxImageExtent.width, extent.width)); | ||
| 50 | extent.height = std::max(capabilities.minImageExtent.height, | ||
| 51 | std::min(capabilities.maxImageExtent.height, extent.height)); | ||
| 52 | return extent; | ||
| 53 | } | ||
| 54 | } // namespace | ||
| 55 | |||
| 56 | VKSwapchain::VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device) | ||
| 57 | : surface{surface}, device{device} {} | ||
| 58 | |||
| 59 | VKSwapchain::~VKSwapchain() = default; | ||
| 60 | |||
| 61 | void VKSwapchain::Create(u32 width, u32 height) { | ||
| 62 | const auto dev = device.GetLogical(); | ||
| 63 | const auto& dld = device.GetDispatchLoader(); | ||
| 64 | const auto physical_device = device.GetPhysical(); | ||
| 65 | |||
| 66 | const vk::SurfaceCapabilitiesKHR capabilities{ | ||
| 67 | physical_device.getSurfaceCapabilitiesKHR(surface, dld)}; | ||
| 68 | if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) { | ||
| 69 | return; | ||
| 70 | } | ||
| 71 | |||
| 72 | dev.waitIdle(dld); | ||
| 73 | Destroy(); | ||
| 74 | |||
| 75 | CreateSwapchain(capabilities, width, height); | ||
| 76 | CreateSemaphores(); | ||
| 77 | CreateImageViews(); | ||
| 78 | |||
| 79 | fences.resize(image_count, nullptr); | ||
| 80 | } | ||
| 81 | |||
| 82 | void VKSwapchain::AcquireNextImage() { | ||
| 83 | const auto dev{device.GetLogical()}; | ||
| 84 | const auto& dld{device.GetDispatchLoader()}; | ||
| 85 | dev.acquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(), | ||
| 86 | *present_semaphores[frame_index], {}, &image_index, dld); | ||
| 87 | |||
| 88 | if (auto& fence = fences[image_index]; fence) { | ||
| 89 | fence->Wait(); | ||
| 90 | fence->Release(); | ||
| 91 | fence = nullptr; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | bool VKSwapchain::Present(vk::Semaphore render_semaphore, VKFence& fence) { | ||
| 96 | const vk::Semaphore present_semaphore{*present_semaphores[frame_index]}; | ||
| 97 | const std::array<vk::Semaphore, 2> semaphores{present_semaphore, render_semaphore}; | ||
| 98 | const u32 wait_semaphore_count{render_semaphore ? 2U : 1U}; | ||
| 99 | const auto& dld{device.GetDispatchLoader()}; | ||
| 100 | const auto present_queue{device.GetPresentQueue()}; | ||
| 101 | bool recreated = false; | ||
| 102 | |||
| 103 | const vk::PresentInfoKHR present_info(wait_semaphore_count, semaphores.data(), 1, | ||
| 104 | &swapchain.get(), &image_index, {}); | ||
| 105 | switch (const auto result = present_queue.presentKHR(&present_info, dld); result) { | ||
| 106 | case vk::Result::eSuccess: | ||
| 107 | break; | ||
| 108 | case vk::Result::eErrorOutOfDateKHR: | ||
| 109 | if (current_width > 0 && current_height > 0) { | ||
| 110 | Create(current_width, current_height); | ||
| 111 | recreated = true; | ||
| 112 | } | ||
| 113 | break; | ||
| 114 | default: | ||
| 115 | LOG_CRITICAL(Render_Vulkan, "Vulkan failed to present swapchain due to {}!", | ||
| 116 | vk::to_string(result)); | ||
| 117 | UNREACHABLE(); | ||
| 118 | } | ||
| 119 | |||
| 120 | ASSERT(fences[image_index] == nullptr); | ||
| 121 | fences[image_index] = &fence; | ||
| 122 | frame_index = (frame_index + 1) % image_count; | ||
| 123 | return recreated; | ||
| 124 | } | ||
| 125 | |||
| 126 | bool VKSwapchain::HasFramebufferChanged(const Layout::FramebufferLayout& framebuffer) const { | ||
| 127 | // TODO(Rodrigo): Handle framebuffer pixel format changes | ||
| 128 | return framebuffer.width != current_width || framebuffer.height != current_height; | ||
| 129 | } | ||
| 130 | |||
| 131 | void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, | ||
| 132 | u32 height) { | ||
| 133 | const auto dev{device.GetLogical()}; | ||
| 134 | const auto& dld{device.GetDispatchLoader()}; | ||
| 135 | const auto physical_device{device.GetPhysical()}; | ||
| 136 | |||
| 137 | const std::vector<vk::SurfaceFormatKHR> formats{ | ||
| 138 | physical_device.getSurfaceFormatsKHR(surface, dld)}; | ||
| 139 | |||
| 140 | const std::vector<vk::PresentModeKHR> present_modes{ | ||
| 141 | physical_device.getSurfacePresentModesKHR(surface, dld)}; | ||
| 142 | |||
| 143 | const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)}; | ||
| 144 | const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)}; | ||
| 145 | extent = ChooseSwapExtent(capabilities, width, height); | ||
| 146 | |||
| 147 | current_width = extent.width; | ||
| 148 | current_height = extent.height; | ||
| 149 | |||
| 150 | u32 requested_image_count{capabilities.minImageCount + 1}; | ||
| 151 | if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { | ||
| 152 | requested_image_count = capabilities.maxImageCount; | ||
| 153 | } | ||
| 154 | |||
| 155 | vk::SwapchainCreateInfoKHR swapchain_ci( | ||
| 156 | {}, surface, requested_image_count, surface_format.format, surface_format.colorSpace, | ||
| 157 | extent, 1, vk::ImageUsageFlagBits::eColorAttachment, {}, {}, {}, | ||
| 158 | capabilities.currentTransform, vk::CompositeAlphaFlagBitsKHR::eOpaque, present_mode, false, | ||
| 159 | {}); | ||
| 160 | |||
| 161 | const u32 graphics_family{device.GetGraphicsFamily()}; | ||
| 162 | const u32 present_family{device.GetPresentFamily()}; | ||
| 163 | const std::array<u32, 2> queue_indices{graphics_family, present_family}; | ||
| 164 | if (graphics_family != present_family) { | ||
| 165 | swapchain_ci.imageSharingMode = vk::SharingMode::eConcurrent; | ||
| 166 | swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size()); | ||
| 167 | swapchain_ci.pQueueFamilyIndices = queue_indices.data(); | ||
| 168 | } else { | ||
| 169 | swapchain_ci.imageSharingMode = vk::SharingMode::eExclusive; | ||
| 170 | } | ||
| 171 | |||
| 172 | swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld); | ||
| 173 | |||
| 174 | images = dev.getSwapchainImagesKHR(*swapchain, dld); | ||
| 175 | image_count = static_cast<u32>(images.size()); | ||
| 176 | image_format = surface_format.format; | ||
| 177 | } | ||
| 178 | |||
| 179 | void VKSwapchain::CreateSemaphores() { | ||
| 180 | const auto dev{device.GetLogical()}; | ||
| 181 | const auto& dld{device.GetDispatchLoader()}; | ||
| 182 | |||
| 183 | present_semaphores.resize(image_count); | ||
| 184 | for (std::size_t i = 0; i < image_count; i++) { | ||
| 185 | present_semaphores[i] = dev.createSemaphoreUnique({}, nullptr, dld); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | void VKSwapchain::CreateImageViews() { | ||
| 190 | const auto dev{device.GetLogical()}; | ||
| 191 | const auto& dld{device.GetDispatchLoader()}; | ||
| 192 | |||
| 193 | image_views.resize(image_count); | ||
| 194 | for (std::size_t i = 0; i < image_count; i++) { | ||
| 195 | const vk::ImageViewCreateInfo image_view_ci({}, images[i], vk::ImageViewType::e2D, | ||
| 196 | image_format, {}, | ||
| 197 | {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}); | ||
| 198 | image_views[i] = dev.createImageViewUnique(image_view_ci, nullptr, dld); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | void VKSwapchain::Destroy() { | ||
| 203 | frame_index = 0; | ||
| 204 | present_semaphores.clear(); | ||
| 205 | framebuffers.clear(); | ||
| 206 | image_views.clear(); | ||
| 207 | swapchain.reset(); | ||
| 208 | } | ||
| 209 | |||
| 210 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h new file mode 100644 index 000000000..2ad84f185 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_swapchain.h | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 11 | |||
| 12 | namespace Layout { | ||
| 13 | struct FramebufferLayout; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Vulkan { | ||
| 17 | |||
| 18 | class VKDevice; | ||
| 19 | class VKFence; | ||
| 20 | |||
| 21 | class VKSwapchain { | ||
| 22 | public: | ||
| 23 | explicit VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device); | ||
| 24 | ~VKSwapchain(); | ||
| 25 | |||
| 26 | /// Creates (or recreates) the swapchain with a given size. | ||
| 27 | void Create(u32 width, u32 height); | ||
| 28 | |||
| 29 | /// Acquires the next image in the swapchain, waits as needed. | ||
| 30 | void AcquireNextImage(); | ||
| 31 | |||
| 32 | /// Presents the rendered image to the swapchain. Returns true when the swapchains had to be | ||
| 33 | /// recreated. Takes responsability for the ownership of fence. | ||
| 34 | bool Present(vk::Semaphore render_semaphore, VKFence& fence); | ||
| 35 | |||
| 36 | /// Returns true when the framebuffer layout has changed. | ||
| 37 | bool HasFramebufferChanged(const Layout::FramebufferLayout& framebuffer) const; | ||
| 38 | |||
| 39 | const vk::Extent2D& GetSize() const { | ||
| 40 | return extent; | ||
| 41 | } | ||
| 42 | |||
| 43 | u32 GetImageCount() const { | ||
| 44 | return image_count; | ||
| 45 | } | ||
| 46 | |||
| 47 | u32 GetImageIndex() const { | ||
| 48 | return image_index; | ||
| 49 | } | ||
| 50 | |||
| 51 | vk::Image GetImageIndex(u32 index) const { | ||
| 52 | return images[index]; | ||
| 53 | } | ||
| 54 | |||
| 55 | vk::ImageView GetImageViewIndex(u32 index) const { | ||
| 56 | return *image_views[index]; | ||
| 57 | } | ||
| 58 | |||
| 59 | vk::Format GetImageFormat() const { | ||
| 60 | return image_format; | ||
| 61 | } | ||
| 62 | |||
| 63 | private: | ||
| 64 | void CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, u32 height); | ||
| 65 | void CreateSemaphores(); | ||
| 66 | void CreateImageViews(); | ||
| 67 | |||
| 68 | void Destroy(); | ||
| 69 | |||
| 70 | const vk::SurfaceKHR surface; | ||
| 71 | const VKDevice& device; | ||
| 72 | |||
| 73 | UniqueSwapchainKHR swapchain; | ||
| 74 | |||
| 75 | u32 image_count{}; | ||
| 76 | std::vector<vk::Image> images; | ||
| 77 | std::vector<UniqueImageView> image_views; | ||
| 78 | std::vector<UniqueFramebuffer> framebuffers; | ||
| 79 | std::vector<VKFence*> fences; | ||
| 80 | std::vector<UniqueSemaphore> present_semaphores; | ||
| 81 | |||
| 82 | u32 image_index{}; | ||
| 83 | u32 frame_index{}; | ||
| 84 | |||
| 85 | vk::Format image_format{}; | ||
| 86 | vk::Extent2D extent{}; | ||
| 87 | |||
| 88 | u32 current_width{}; | ||
| 89 | u32 current_height{}; | ||
| 90 | }; | ||
| 91 | |||
| 92 | } // namespace Vulkan | ||
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp index 730426c16..f95f7fe3c 100644 --- a/src/yuzu/applets/profile_select.cpp +++ b/src/yuzu/applets/profile_select.cpp | |||
| @@ -58,10 +58,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent) | |||
| 58 | 58 | ||
| 59 | scroll_area = new QScrollArea; | 59 | scroll_area = new QScrollArea; |
| 60 | 60 | ||
| 61 | buttons = new QDialogButtonBox; | 61 | buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); |
| 62 | buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); | ||
| 63 | buttons->addButton(tr("OK"), QDialogButtonBox::AcceptRole); | ||
| 64 | |||
| 65 | connect(buttons, &QDialogButtonBox::accepted, this, &QtProfileSelectionDialog::accept); | 62 | connect(buttons, &QDialogButtonBox::accepted, this, &QtProfileSelectionDialog::accept); |
| 66 | connect(buttons, &QDialogButtonBox::rejected, this, &QtProfileSelectionDialog::reject); | 63 | connect(buttons, &QDialogButtonBox::rejected, this, &QtProfileSelectionDialog::reject); |
| 67 | 64 | ||
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index eddc9c941..f3eb29b25 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp | |||
| @@ -75,13 +75,13 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( | |||
| 75 | length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); | 75 | length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); |
| 76 | }); | 76 | }); |
| 77 | 77 | ||
| 78 | buttons = new QDialogButtonBox; | 78 | buttons = new QDialogButtonBox(QDialogButtonBox::Cancel); |
| 79 | buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); | 79 | if (parameters.submit_text.empty()) { |
| 80 | buttons->addButton(parameters.submit_text.empty() | 80 | buttons->addButton(QDialogButtonBox::Ok); |
| 81 | ? tr("OK") | 81 | } else { |
| 82 | : QString::fromStdU16String(parameters.submit_text), | 82 | buttons->addButton(QString::fromStdU16String(parameters.submit_text), |
| 83 | QDialogButtonBox::AcceptRole); | 83 | QDialogButtonBox::AcceptRole); |
| 84 | 84 | } | |
| 85 | connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); | 85 | connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); |
| 86 | connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); | 86 | connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); |
| 87 | layout->addWidget(header_label); | 87 | layout->addWidget(header_label); |
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp index 8b30e0a85..86e03e46d 100644 --- a/src/yuzu/debugger/profiler.cpp +++ b/src/yuzu/debugger/profiler.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <QMouseEvent> | 7 | #include <QMouseEvent> |
| 8 | #include <QPainter> | 8 | #include <QPainter> |
| 9 | #include <QString> | 9 | #include <QString> |
| 10 | #include <QTimer> | ||
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 11 | #include "common/microprofile.h" | 12 | #include "common/microprofile.h" |
| 12 | #include "yuzu/debugger/profiler.h" | 13 | #include "yuzu/debugger/profiler.h" |
diff --git a/src/yuzu/debugger/profiler.h b/src/yuzu/debugger/profiler.h index eae1e9e3c..8e69fdb06 100644 --- a/src/yuzu/debugger/profiler.h +++ b/src/yuzu/debugger/profiler.h | |||
| @@ -4,10 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <QAbstractItemModel> | 7 | #include <QWidget> |
| 8 | #include <QDockWidget> | 8 | |
| 9 | #include <QTimer> | 9 | class QAction; |
| 10 | #include "common/microprofile.h" | 10 | class QHideEvent; |
| 11 | class QShowEvent; | ||
| 11 | 12 | ||
| 12 | class MicroProfileDialog : public QWidget { | 13 | class MicroProfileDialog : public QWidget { |
| 13 | Q_OBJECT | 14 | Q_OBJECT |