From 5c7b8e9d6ca0b5247b4f00fb2c46c52ff88c730b Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Mon, 8 Feb 2021 06:07:34 +0100 Subject: [PATCH] early-access version 1424 --- README.md | 2 +- src/core/hle/kernel/svc.cpp | 247 +++++++++++++----- src/input_common/mouse/mouse_input.cpp | 16 +- .../renderer_opengl/gl_texture_cache.cpp | 23 +- src/yuzu/bootmanager.cpp | 31 +-- .../emu_window/emu_window_sdl2_gl.cpp | 26 +- 6 files changed, 231 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 64b9db49a..8bac8d355 100755 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f47349285..e67e534b3 100755 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -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 thread = handle_table.Get(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 thread = handle_table.Get(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 thread = handle_table.Get(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 thread = current_process->GetHandleTable().Get(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 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 thread = handle_table.Get(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 thread = handle_table.Get(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 thread = handle_table.Get(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 thread = handle_table.Get(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 thread = handle_table.Get(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(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(); diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index 0af7be8ca..67a584d53 100755 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp @@ -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(12 * info.last_mouse_change.x), - static_cast(12 * -info.last_mouse_change.y)}; + info.data.axis = {static_cast(16 * info.last_mouse_change.x), + static_cast(16 * -info.last_mouse_change.y)}; info.tilt_direction = info.last_mouse_change; info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity; continue; diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 31eb54123..6c7688135 100755 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -96,7 +96,7 @@ constexpr std::array 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 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()) { diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index e1085c0dd..1c61d419d 100755 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -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(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.

GL Renderer:
%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: {}", diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index a103b04bd..deddea9ee 100755 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -59,29 +59,17 @@ private: bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { std::vector 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);