Browse Source

[video_core/vic] Partial revert to fix Link Awakening's blue tint (#3348)

fixes link awakening intro screen on non-SSE 4.1

Signed-off-by: lizzie lizzie@eden-emu.dev
Co-authored-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3348
Reviewed-by: DraVee <dravee@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
pull/3353/head
lizzie 2 weeks ago
committed by crueter
parent
commit
8663913510
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 2
      src/android/app/build.gradle.kts
  2. 2
      src/common/logging/text_formatter.cpp
  3. 85
      src/video_core/host1x/vic.cpp
  4. 2
      src/video_core/texture_cache/texture_cache.h
  5. 2
      src/yuzu/main_window.cpp
  6. 2
      src/yuzu/main_window.h

2
src/android/app/build.gradle.kts

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project

2
src/common/logging/text_formatter.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2014 Citra Emulator Project

85
src/video_core/host1x/vic.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -485,8 +485,8 @@ void Vic::Blend(const ConfigStruct& config, const SlotStruct& slot, VideoPixelFo
source_bottom = (std::min)(source_bottom, out_surface_height);
source_right = (std::min)(source_right, out_surface_width);
auto const work_width = u32((std::max)(0, s32(source_right) - s32(source_left)));
auto const work_height = u32((std::max)(0, s32(source_bottom) - s32(source_top)));
[[maybe_unused]] auto const work_width = u32((std::max)(0, s32(source_right) - s32(source_left)));
[[maybe_unused]] auto const work_height = u32((std::max)(0, s32(source_bottom) - s32(source_top)));
// TODO Alpha blending. No games I've seen use more than a single surface or supply an alpha
// below max, so it's ignored for now.
@ -630,42 +630,49 @@ void Vic::Blend(const ConfigStruct& config, const SlotStruct& slot, VideoPixelFo
// | r1c0 r1c1 r1c2 r1c3 | * | G | = | G |
// | r2c0 r2c1 r2c2 r2c3 | | B | | B |
// | 1 |
auto const shift = s32(slot.color_matrix.matrix_r_shift.Value());
struct AliasedMatrixType { u64 m[4]; };
static_assert(sizeof(AliasedMatrixType) == sizeof(slot.color_matrix));
u64 const mat_mask = (1 << 20) - 1;
auto const* amt = reinterpret_cast<AliasedMatrixType const*>(&slot.color_matrix);
constexpr s32 shifts[4] = { 0, 20, 40, 60 };
s32 mr[4][4];
for (u32 j = 0; j < 3; ++j)
for (u32 i = 0; i < 4; ++i)
mr[j][i] = s32(s64(((amt->m[i] >> shifts[j]) & mat_mask) << (64 - 20)) >> (64 - 20));
auto const clamp_min = s32(slot.config.soft_clamp_low.Value());
auto const clamp_max = s32(slot.config.soft_clamp_high.Value());
for (u32 y = 0; y < work_height; ++y) {
auto const src = (y + source_top) * in_surface_width + source_left;
auto const dst = (y + source_top) * out_surface_width + rect_left;
for (u32 x = 0; x < work_width; ++x) {
auto const& in_pixel = slot_surface[src + x];
auto& out_pixel = output_surface[dst + x];
s32 const mul_values[4] = {
in_pixel.r * mr[0][0] + in_pixel.g * mr[1][1] + in_pixel.b * mr[0][2],
in_pixel.r * mr[1][0] + in_pixel.g * mr[1][1] + in_pixel.b * mr[1][2],
in_pixel.r * mr[2][0] + in_pixel.g * mr[2][1] + in_pixel.b * mr[2][2],
s32(in_pixel.a)
};
s32 const mul_clamp[4] = {
std::clamp(((mul_values[0] >> shift) + mr[0][3]) >> 8, clamp_min, clamp_max),
std::clamp(((mul_values[1] >> shift) + mr[1][3]) >> 8, clamp_min, clamp_max),
std::clamp(((mul_values[2] >> shift) + mr[2][3]) >> 8, clamp_min, clamp_max),
std::clamp(mul_values[3], clamp_min, clamp_max)
};
out_pixel = format == VideoPixelFormat::A8R8G8B8
? Pixel(u16(mul_clamp[2]), u16(mul_clamp[1]), u16(mul_clamp[0]), u16(mul_clamp[3]))
: Pixel(u16(mul_clamp[0]), u16(mul_clamp[1]), u16(mul_clamp[2]), u16(mul_clamp[3]));
const auto r0c0 = s32(slot.color_matrix.matrix_coeff00.Value());
const auto r0c1 = s32(slot.color_matrix.matrix_coeff01.Value());
const auto r0c2 = s32(slot.color_matrix.matrix_coeff02.Value());
const auto r0c3 = s32(slot.color_matrix.matrix_coeff03.Value());
const auto r1c0 = s32(slot.color_matrix.matrix_coeff10.Value());
const auto r1c1 = s32(slot.color_matrix.matrix_coeff11.Value());
const auto r1c2 = s32(slot.color_matrix.matrix_coeff12.Value());
const auto r1c3 = s32(slot.color_matrix.matrix_coeff13.Value());
const auto r2c0 = s32(slot.color_matrix.matrix_coeff20.Value());
const auto r2c1 = s32(slot.color_matrix.matrix_coeff21.Value());
const auto r2c2 = s32(slot.color_matrix.matrix_coeff22.Value());
const auto r2c3 = s32(slot.color_matrix.matrix_coeff23.Value());
const auto shift = s32(slot.color_matrix.matrix_r_shift.Value());
const auto clamp_min = s32(slot.config.soft_clamp_low.Value());
const auto clamp_max = s32(slot.config.soft_clamp_high.Value());
auto MatMul = [&](const Pixel& in_pixel) -> std::tuple<s32, s32, s32, s32> {
auto r = s32(in_pixel.r);
auto g = s32(in_pixel.g);
auto b = s32(in_pixel.b);
r = in_pixel.r * r0c0 + in_pixel.g * r0c1 + in_pixel.b * r0c2;
g = in_pixel.r * r1c0 + in_pixel.g * r1c1 + in_pixel.b * r1c2;
b = in_pixel.r * r2c0 + in_pixel.g * r2c1 + in_pixel.b * r2c2;
r >>= shift;
g >>= shift;
b >>= shift;
r += r0c3;
g += r1c3;
b += r2c3;
r >>= 8;
g >>= 8;
b >>= 8;
return {r, g, b, s32(in_pixel.a)};
};
for (u32 y = source_top; y < source_bottom; y++) {
const auto src{y * in_surface_width + source_left};
const auto dst{y * out_surface_width + rect_left};
for (u32 x = source_left; x < source_right; x++) {
auto [r, g, b, a] = MatMul(slot_surface[src + x]);
r = std::clamp(r, clamp_min, clamp_max);
g = std::clamp(g, clamp_min, clamp_max);
b = std::clamp(b, clamp_min, clamp_max);
a = std::clamp(a, clamp_min, clamp_max);
output_surface[dst + x] = {u16(r), u16(g), u16(b), u16(a)};
}
}
}

2
src/video_core/texture_cache/texture_cache.h

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project

2
src/yuzu/main_window.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// Qt on macOS doesn't define VMA shit

2
src/yuzu/main_window.h

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2014 Citra Emulator Project

Loading…
Cancel
Save