forked from etc/pineapple-src
early-access version 1424
This commit is contained in:
parent
5ff3465447
commit
5c7b8e9d6c
6 changed files with 231 additions and 114 deletions
|
@ -1,7 +1,7 @@
|
|||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 1423.
|
||||
This is the source code for early-access 1424.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
|
|
@ -374,7 +374,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t
|
|||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Get the thread's id.
|
||||
*out_thread_id = thread->GetThreadID();
|
||||
|
@ -484,7 +487,10 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
|
|||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Cancel the thread's wait.
|
||||
thread->WaitCancel();
|
||||
|
@ -502,8 +508,15 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd
|
|||
thread_handle, address, tag);
|
||||
|
||||
// Validate the input address.
|
||||
R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress);
|
||||
if (Memory::IsKernelAddress(address)) {
|
||||
LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})",
|
||||
address);
|
||||
return ResultInvalidCurrentMemory;
|
||||
}
|
||||
if (!Common::IsAligned(address, sizeof(u32))) {
|
||||
LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
|
||||
return ResultInvalidAddress;
|
||||
}
|
||||
|
||||
return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
|
||||
}
|
||||
|
@ -518,8 +531,16 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
|
|||
LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
|
||||
|
||||
// Validate the input address.
|
||||
R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress);
|
||||
if (Memory::IsKernelAddress(address)) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Attempting to arbitrate an unlock on a kernel address (address={:08X})",
|
||||
address);
|
||||
return ResultInvalidCurrentMemory;
|
||||
}
|
||||
if (!Common::IsAligned(address, sizeof(u32))) {
|
||||
LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
|
||||
return ResultInvalidAddress;
|
||||
}
|
||||
|
||||
return system.Kernel().CurrentProcess()->SignalToAddress(address);
|
||||
}
|
||||
|
@ -1031,37 +1052,47 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
|
|||
return UnmapPhysicalMemory(system, addr, size);
|
||||
}
|
||||
|
||||
constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
|
||||
switch (thread_activity) {
|
||||
case Svc::ThreadActivity::Runnable:
|
||||
case Svc::ThreadActivity::Paused:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the thread activity
|
||||
static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
|
||||
Svc::ThreadActivity thread_activity) {
|
||||
ThreadActivity thread_activity) {
|
||||
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
|
||||
thread_activity);
|
||||
|
||||
// Validate the activity.
|
||||
R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue);
|
||||
constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
|
||||
return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
|
||||
};
|
||||
if (!IsValidThreadActivity(thread_activity)) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})",
|
||||
thread_activity);
|
||||
return ResultInvalidEnumValue;
|
||||
}
|
||||
|
||||
// Get the thread from its handle.
|
||||
auto& kernel = system.Kernel();
|
||||
const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Check that the activity is being set on a non-current thread for the current process.
|
||||
R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle);
|
||||
R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy);
|
||||
if (thread->GetOwnerProcess() != kernel.CurrentProcess()) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread.");
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
if (thread.get() == GetCurrentThreadPointer(kernel)) {
|
||||
LOG_ERROR(Kernel_SVC, "Thread is busy");
|
||||
return ResultBusy;
|
||||
}
|
||||
|
||||
// Set the activity.
|
||||
R_TRY(thread->SetActivity(thread_activity));
|
||||
const auto set_result = thread->SetActivity(thread_activity);
|
||||
if (set_result.IsError()) {
|
||||
LOG_ERROR(Kernel_SVC, "Failed to set thread activity.");
|
||||
return set_result;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -1080,16 +1111,29 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
|
|||
const auto* current_process = system.Kernel().CurrentProcess();
|
||||
const std::shared_ptr<KThread> thread =
|
||||
current_process->GetHandleTable().Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Require the handle be to a non-current thread in the current process.
|
||||
R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle);
|
||||
R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(),
|
||||
Svc::ResultBusy);
|
||||
if (thread->GetOwnerProcess() != current_process) {
|
||||
LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process.");
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
|
||||
LOG_ERROR(Kernel_SVC, "Current thread is busy.");
|
||||
return ResultBusy;
|
||||
}
|
||||
|
||||
// Get the thread context.
|
||||
std::vector<u8> context;
|
||||
R_TRY(thread->GetThreadContext3(context));
|
||||
const auto context_result = thread->GetThreadContext3(context);
|
||||
if (context_result.IsError()) {
|
||||
LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})",
|
||||
context_result.raw);
|
||||
return context_result;
|
||||
}
|
||||
|
||||
// Copy the thread context to user space.
|
||||
system.Memory().WriteBlock(out_context, context.data(), context.size());
|
||||
|
@ -1108,7 +1152,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han
|
|||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Get the thread's priority.
|
||||
*out_priority = thread->GetPriority();
|
||||
|
@ -1124,13 +1171,18 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
|
|||
LOG_TRACE(Kernel_SVC, "called");
|
||||
|
||||
// Validate the priority.
|
||||
R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
|
||||
Svc::ResultInvalidPriority);
|
||||
if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority);
|
||||
return ResultInvalidPriority;
|
||||
}
|
||||
|
||||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Set the thread priority.
|
||||
thread->SetBasePriority(priority);
|
||||
|
@ -1446,17 +1498,28 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
|
|||
// Adjust core id, if it's the default magic.
|
||||
auto& kernel = system.Kernel();
|
||||
auto& process = *kernel.CurrentProcess();
|
||||
if (core_id == Svc::IdealCoreUseProcessValue) {
|
||||
if (core_id == IdealCoreUseProcessValue) {
|
||||
core_id = process.GetIdealCoreId();
|
||||
}
|
||||
|
||||
// Validate arguments.
|
||||
R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId);
|
||||
R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId);
|
||||
if (!IsValidCoreId(core_id)) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id);
|
||||
return ResultInvalidCoreId;
|
||||
}
|
||||
if (((1ULL << core_id) & process.GetCoreMask()) == 0) {
|
||||
LOG_ERROR(Kernel_SVC, "Core ID doesn't fall within allowable cores (id={})", core_id);
|
||||
return ResultInvalidCoreId;
|
||||
}
|
||||
|
||||
R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
|
||||
Svc::ResultInvalidPriority);
|
||||
R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
|
||||
if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid priority specified (priority={})", priority);
|
||||
return ResultInvalidPriority;
|
||||
}
|
||||
if (!process.CheckThreadPriority(priority)) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid allowable thread priority (priority={})", priority);
|
||||
return ResultInvalidPriority;
|
||||
}
|
||||
|
||||
KScopedResourceReservation thread_reservation(
|
||||
kernel.CurrentProcess(), LimitableResource::Threads, 1,
|
||||
|
@ -1501,10 +1564,19 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
|
|||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Try to start the thread.
|
||||
R_TRY(thread->Run());
|
||||
const auto run_result = thread->Run();
|
||||
if (run_result.IsError()) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Unable to successfuly start thread (thread handle={:08X}, result={})",
|
||||
thread_handle, run_result.raw);
|
||||
return run_result;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -1565,8 +1637,14 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address,
|
|||
cv_key, tag, timeout_ns);
|
||||
|
||||
// Validate input.
|
||||
R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress);
|
||||
if (Memory::IsKernelAddress(address)) {
|
||||
LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address);
|
||||
return ResultInvalidCurrentMemory;
|
||||
}
|
||||
if (!Common::IsAligned(address, sizeof(s32))) {
|
||||
LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address);
|
||||
return ResultInvalidAddress;
|
||||
}
|
||||
|
||||
// Convert timeout from nanoseconds to ticks.
|
||||
s64 timeout{};
|
||||
|
@ -1641,9 +1719,18 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit
|
|||
address, arb_type, value, timeout_ns);
|
||||
|
||||
// Validate input.
|
||||
R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress);
|
||||
R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue);
|
||||
if (Memory::IsKernelAddress(address)) {
|
||||
LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address);
|
||||
return ResultInvalidCurrentMemory;
|
||||
}
|
||||
if (!Common::IsAligned(address, sizeof(s32))) {
|
||||
LOG_ERROR(Kernel_SVC, "Wait address must be 4 byte aligned (address={:08X})", address);
|
||||
return ResultInvalidAddress;
|
||||
}
|
||||
if (!IsValidArbitrationType(arb_type)) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid arbitration type specified (type={})", arb_type);
|
||||
return ResultInvalidEnumValue;
|
||||
}
|
||||
|
||||
// Convert timeout from nanoseconds to ticks.
|
||||
s64 timeout{};
|
||||
|
@ -1677,9 +1764,18 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
|
|||
address, signal_type, value, count);
|
||||
|
||||
// Validate input.
|
||||
R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
|
||||
R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress);
|
||||
R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue);
|
||||
if (Memory::IsKernelAddress(address)) {
|
||||
LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address);
|
||||
return ResultInvalidCurrentMemory;
|
||||
}
|
||||
if (!Common::IsAligned(address, sizeof(s32))) {
|
||||
LOG_ERROR(Kernel_SVC, "Signaled address must be 4 byte aligned (address={:08X})", address);
|
||||
return ResultInvalidAddress;
|
||||
}
|
||||
if (!IsValidSignalType(signal_type)) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid signal type specified (type={})", signal_type);
|
||||
return ResultInvalidEnumValue;
|
||||
}
|
||||
|
||||
return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
|
||||
count);
|
||||
|
@ -1835,10 +1931,17 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
|
|||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Get the core mask.
|
||||
R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask));
|
||||
const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -1866,26 +1969,46 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
|
|||
} else {
|
||||
// Validate the affinity mask.
|
||||
const u64 process_core_mask = current_process.GetCoreMask();
|
||||
R_UNLESS((affinity_mask | process_core_mask) == process_core_mask,
|
||||
Svc::ResultInvalidCoreId);
|
||||
R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination);
|
||||
if ((affinity_mask | process_core_mask) != process_core_mask) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Affinity mask does match the process core mask (affinity mask={:016X}, core "
|
||||
"mask={:016X})",
|
||||
affinity_mask, process_core_mask);
|
||||
return ResultInvalidCoreId;
|
||||
}
|
||||
if (affinity_mask == 0) {
|
||||
LOG_ERROR(Kernel_SVC, "Affinity mask is zero.");
|
||||
return ResultInvalidCombination;
|
||||
}
|
||||
|
||||
// Validate the core id.
|
||||
if (IsValidCoreId(core_id)) {
|
||||
R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination);
|
||||
if (((1ULL << core_id) & affinity_mask) == 0) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
|
||||
return ResultInvalidCombination;
|
||||
}
|
||||
} else {
|
||||
R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare,
|
||||
Svc::ResultInvalidCoreId);
|
||||
if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
|
||||
return ResultInvalidCoreId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the thread from its handle.
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||
R_UNLESS(thread, Svc::ResultInvalidHandle);
|
||||
if (!thread) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Set the core mask.
|
||||
R_TRY(thread->SetCoreMask(core_id, affinity_mask));
|
||||
const auto set_result = thread->SetCoreMask(core_id, affinity_mask);
|
||||
if (set_result.IsError()) {
|
||||
LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
|
||||
return set_result;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -1913,7 +2036,10 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
|
|||
|
||||
// Get the writable event.
|
||||
auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
|
||||
R_UNLESS(writable_event, Svc::ResultInvalidHandle);
|
||||
if (!writable_event) {
|
||||
LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle);
|
||||
return ResultInvalidHandle;
|
||||
}
|
||||
|
||||
// Commit the successfuly reservation.
|
||||
event_reservation.Commit();
|
||||
|
@ -1965,7 +2091,10 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
|
|||
|
||||
// Create a new event.
|
||||
const auto event = KEvent::Create(kernel, "CreateEvent");
|
||||
R_UNLESS(event != nullptr, Svc::ResultOutOfResource);
|
||||
if (!event) {
|
||||
LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached.");
|
||||
return ResultOutOfResource;
|
||||
}
|
||||
|
||||
// Initialize the event.
|
||||
event->Initialize();
|
||||
|
|
|
@ -37,7 +37,7 @@ void Mouse::UpdateThread() {
|
|||
if (configuring) {
|
||||
UpdateYuzuSettings();
|
||||
}
|
||||
if (mouse_panning_timout++ > 12) {
|
||||
if (mouse_panning_timout++ > 8) {
|
||||
StopPanning();
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
|
||||
|
@ -72,11 +72,9 @@ void Mouse::PressButton(int x, int y, int button_) {
|
|||
void Mouse::StopPanning() {
|
||||
for (MouseInfo& info : mouse_info) {
|
||||
if (Settings::values.mouse_panning) {
|
||||
if (info.data.pressed) {
|
||||
continue;
|
||||
}
|
||||
info.data.axis = {0, 0};
|
||||
info.data.axis = {};
|
||||
info.tilt_speed = 0;
|
||||
info.last_mouse_change = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,17 +83,15 @@ void Mouse::MouseMove(int x, int y, int center_x, int center_y) {
|
|||
for (MouseInfo& info : mouse_info) {
|
||||
if (Settings::values.mouse_panning) {
|
||||
const auto mouse_change = Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y);
|
||||
const auto length =
|
||||
(mouse_change.y * mouse_change.y) + (mouse_change.x * mouse_change.x);
|
||||
mouse_panning_timout = 0;
|
||||
|
||||
if (info.data.pressed || length < 4) {
|
||||
if (mouse_change.y == 0 && mouse_change.x == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
info.last_mouse_change = (info.last_mouse_change * 0.8f) + (mouse_change * 0.2f);
|
||||
info.data.axis = {static_cast<int>(12 * info.last_mouse_change.x),
|
||||
static_cast<int>(12 * -info.last_mouse_change.y)};
|
||||
info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x),
|
||||
static_cast<int>(16 * -info.last_mouse_change.y)};
|
||||
info.tilt_direction = info.last_mouse_change;
|
||||
info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
|
||||
continue;
|
||||
|
|
|
@ -96,7 +96,7 @@ constexpr std::array<FormatTuple, MaxPixelFormat> FORMAT_TABLE = {{
|
|||
{GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UFLOAT
|
||||
{GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SFLOAT
|
||||
{GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4_UNORM
|
||||
{GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
|
||||
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
|
||||
{GL_RGBA32F, GL_RGBA, GL_FLOAT}, // R32G32B32A32_FLOAT
|
||||
{GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, // R32G32B32A32_SINT
|
||||
{GL_RG32F, GL_RG, GL_FLOAT}, // R32G32_FLOAT
|
||||
|
@ -125,7 +125,7 @@ constexpr std::array<FormatTuple, MaxPixelFormat> FORMAT_TABLE = {{
|
|||
{GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8_UNORM
|
||||
{GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5_UNORM
|
||||
{GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4_UNORM
|
||||
{GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
|
||||
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE}, // B8G8R8A8_SRGB
|
||||
{GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // BC1_RGBA_SRGB
|
||||
{GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // BC2_SRGB
|
||||
{GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // BC3_SRGB
|
||||
|
@ -396,6 +396,18 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) {
|
|||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsPixelFormatBGRA(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::B5G6R5_UNORM:
|
||||
case PixelFormat::B10G11R11_FLOAT:
|
||||
case PixelFormat::B8G8R8A8_UNORM:
|
||||
case PixelFormat::B8G8R8A8_SRGB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
ImageBufferMap::~ImageBufferMap() {
|
||||
|
@ -944,7 +956,12 @@ void ImageView::SetupView(const Device& device, Image& image, ImageViewType view
|
|||
glTextureView(handle, target, parent, internal_format, view_range.base.level,
|
||||
view_range.extent.levels, view_range.base.layer, view_range.extent.layers);
|
||||
if (!info.IsRenderTarget()) {
|
||||
ApplySwizzle(handle, format, info.Swizzle());
|
||||
auto swizzle = info.Swizzle();
|
||||
if (IsPixelFormatBGRA(image.info.format)) {
|
||||
// Swap the R and B channels of the swizzle.
|
||||
std::swap(swizzle[0], swizzle[2]);
|
||||
}
|
||||
ApplySwizzle(handle, format, swizzle);
|
||||
}
|
||||
}
|
||||
if (device.HasDebuggingToolAttached()) {
|
||||
|
|
|
@ -126,7 +126,7 @@ public:
|
|||
/// Create the original context that should be shared from
|
||||
explicit OpenGLSharedContext(QSurface* surface) : surface(surface) {
|
||||
QSurfaceFormat format;
|
||||
format.setVersion(4, 3);
|
||||
format.setVersion(4, 6);
|
||||
format.setProfile(QSurfaceFormat::CompatibilityProfile);
|
||||
format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
|
||||
if (Settings::values.renderer_debug) {
|
||||
|
@ -656,10 +656,10 @@ bool GRenderWindow::LoadOpenGL() {
|
|||
const QString renderer =
|
||||
QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
|
||||
|
||||
if (!GLAD_GL_VERSION_4_3) {
|
||||
LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString());
|
||||
QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"),
|
||||
tr("Your GPU may not support OpenGL 4.3, or you do not have the "
|
||||
if (!GLAD_GL_VERSION_4_6) {
|
||||
LOG_ERROR(Frontend, "GPU does not support OpenGL 4.6: {}", renderer.toStdString());
|
||||
QMessageBox::warning(this, tr("Error while initializing OpenGL 4.6!"),
|
||||
tr("Your GPU may not support OpenGL 4.6, or you do not have the "
|
||||
"latest graphics driver.<br><br>GL Renderer:<br>%1")
|
||||
.arg(renderer));
|
||||
return false;
|
||||
|
@ -682,26 +682,13 @@ bool GRenderWindow::LoadOpenGL() {
|
|||
QStringList GRenderWindow::GetUnsupportedGLExtensions() const {
|
||||
QStringList unsupported_ext;
|
||||
|
||||
if (!GLAD_GL_ARB_buffer_storage)
|
||||
unsupported_ext.append(QStringLiteral("ARB_buffer_storage"));
|
||||
if (!GLAD_GL_ARB_direct_state_access)
|
||||
unsupported_ext.append(QStringLiteral("ARB_direct_state_access"));
|
||||
if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
|
||||
unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev"));
|
||||
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
|
||||
unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge"));
|
||||
if (!GLAD_GL_ARB_multi_bind)
|
||||
unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
|
||||
if (!GLAD_GL_ARB_clip_control)
|
||||
unsupported_ext.append(QStringLiteral("ARB_clip_control"));
|
||||
|
||||
// Extensions required to support some texture formats.
|
||||
if (!GLAD_GL_EXT_texture_compression_s3tc)
|
||||
if (!GLAD_GL_EXT_texture_compression_s3tc) {
|
||||
unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc"));
|
||||
if (!GLAD_GL_ARB_texture_compression_rgtc)
|
||||
}
|
||||
if (!GLAD_GL_ARB_texture_compression_rgtc) {
|
||||
unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc"));
|
||||
if (!GLAD_GL_ARB_depth_buffer_float)
|
||||
unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float"));
|
||||
}
|
||||
|
||||
if (!unsupported_ext.empty()) {
|
||||
LOG_ERROR(Frontend, "GPU does not support all required extensions: {}",
|
||||
|
|
|
@ -59,29 +59,17 @@ private:
|
|||
bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
|
||||
std::vector<std::string_view> unsupported_ext;
|
||||
|
||||
if (!GLAD_GL_ARB_buffer_storage)
|
||||
unsupported_ext.push_back("ARB_buffer_storage");
|
||||
if (!GLAD_GL_ARB_direct_state_access)
|
||||
unsupported_ext.push_back("ARB_direct_state_access");
|
||||
if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
|
||||
unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev");
|
||||
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
|
||||
unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
|
||||
if (!GLAD_GL_ARB_multi_bind)
|
||||
unsupported_ext.push_back("ARB_multi_bind");
|
||||
if (!GLAD_GL_ARB_clip_control)
|
||||
unsupported_ext.push_back("ARB_clip_control");
|
||||
|
||||
// Extensions required to support some texture formats.
|
||||
if (!GLAD_GL_EXT_texture_compression_s3tc)
|
||||
if (!GLAD_GL_EXT_texture_compression_s3tc) {
|
||||
unsupported_ext.push_back("EXT_texture_compression_s3tc");
|
||||
if (!GLAD_GL_ARB_texture_compression_rgtc)
|
||||
}
|
||||
if (!GLAD_GL_ARB_texture_compression_rgtc) {
|
||||
unsupported_ext.push_back("ARB_texture_compression_rgtc");
|
||||
if (!GLAD_GL_ARB_depth_buffer_float)
|
||||
unsupported_ext.push_back("ARB_depth_buffer_float");
|
||||
}
|
||||
|
||||
for (const auto& extension : unsupported_ext)
|
||||
for (const auto& extension : unsupported_ext) {
|
||||
LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension);
|
||||
}
|
||||
|
||||
return unsupported_ext.empty();
|
||||
}
|
||||
|
@ -89,7 +77,7 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
|
|||
EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen)
|
||||
: EmuWindow_SDL2{input_subsystem} {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
|
|
Loading…
Reference in a new issue