Merge pull request #4666 from FearlessTobi/port-2167

Port yuzu-emu/yuzu#2167: "common: Move Quaternion, Rectangle, Vec2, Vec3, and Vec4 into the Common namespace"
This commit is contained in:
bunnei 2019-03-07 23:52:42 -05:00 committed by GitHub
commit 9560060f04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 390 additions and 380 deletions

View File

@ -29,7 +29,7 @@ QImage LoadTexture(const u8* src, const Pica::Texture::TextureInfo& info) {
QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); QImage decoded_image(info.width, info.height, QImage::Format_ARGB32);
for (u32 y = 0; y < info.height; ++y) { for (u32 y = 0; y < info.height; ++y) {
for (u32 x = 0; x < info.width; ++x) { for (u32 x = 0; x < info.width; ++x) {
Math::Vec4<u8> color = Pica::Texture::LookupTexture(src, x, y, info, true); Common::Vec4<u8> color = Pica::Texture::LookupTexture(src, x, y, info, true);
decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a())); decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a()));
} }
} }

View File

@ -585,7 +585,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
for (unsigned int y = 0; y < surface_height; ++y) { for (unsigned int y = 0; y < surface_height; ++y) {
for (unsigned int x = 0; x < surface_width; ++x) { for (unsigned int x = 0; x < surface_width; ++x) {
Math::Vec4<u8> color = Pica::Texture::LookupTexture(buffer, x, y, info, true); Common::Vec4<u8> color = Pica::Texture::LookupTexture(buffer, x, y, info, true);
decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a())); decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a()));
} }
} }
@ -605,7 +605,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
const u32 coarse_y = y & ~7; const u32 coarse_y = y & ~7;
u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
const u8* pixel = buffer + offset; const u8* pixel = buffer + offset;
Math::Vec4<u8> color = {0, 0, 0, 0}; Common::Vec4<u8> color = {0, 0, 0, 0};
switch (surface_format) { switch (surface_format) {
case Format::D16: { case Format::D16: {
@ -622,14 +622,14 @@ void GraphicsSurfaceWidget::OnUpdate() {
break; break;
} }
case Format::D24X8: { case Format::D24X8: {
Math::Vec2<u32> data = Color::DecodeD24S8(pixel); Common::Vec2<u32> data = Color::DecodeD24S8(pixel);
color.r() = data.x & 0xFF; color.r() = data.x & 0xFF;
color.g() = (data.x >> 8) & 0xFF; color.g() = (data.x >> 8) & 0xFF;
color.b() = (data.x >> 16) & 0xFF; color.b() = (data.x >> 16) & 0xFF;
break; break;
} }
case Format::X24S8: { case Format::X24S8: {
Math::Vec2<u32> data = Color::DecodeD24S8(pixel); Common::Vec2<u32> data = Color::DecodeD24S8(pixel);
color.r() = color.g() = color.b() = data.y; color.r() = color.g() = color.b() = data.y;
break; break;
} }

View File

@ -55,36 +55,36 @@ constexpr u8 Convert8To6(u8 value) {
/** /**
* Decode a color stored in RGBA8 format * Decode a color stored in RGBA8 format
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Math::Vec4<u8> DecodeRGBA8(const u8* bytes) { inline Common::Vec4<u8> DecodeRGBA8(const u8* bytes) {
return {bytes[3], bytes[2], bytes[1], bytes[0]}; return {bytes[3], bytes[2], bytes[1], bytes[0]};
} }
/** /**
* Decode a color stored in RGB8 format * Decode a color stored in RGB8 format
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Math::Vec4<u8> DecodeRGB8(const u8* bytes) { inline Common::Vec4<u8> DecodeRGB8(const u8* bytes) {
return {bytes[2], bytes[1], bytes[0], 255}; return {bytes[2], bytes[1], bytes[0], 255};
} }
/** /**
* Decode a color stored in RG8 (aka HILO8) format * Decode a color stored in RG8 (aka HILO8) format
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Math::Vec4<u8> DecodeRG8(const u8* bytes) { inline Common::Vec4<u8> DecodeRG8(const u8* bytes) {
return {bytes[1], bytes[0], 0, 255}; return {bytes[1], bytes[0], 0, 255};
} }
/** /**
* Decode a color stored in RGB565 format * Decode a color stored in RGB565 format
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Math::Vec4<u8> DecodeRGB565(const u8* bytes) { inline Common::Vec4<u8> DecodeRGB565(const u8* bytes) {
u16_le pixel; u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel)); std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F), return {Convert5To8((pixel >> 11) & 0x1F), Convert6To8((pixel >> 5) & 0x3F),
@ -94,9 +94,9 @@ inline Math::Vec4<u8> DecodeRGB565(const u8* bytes) {
/** /**
* Decode a color stored in RGB5A1 format * Decode a color stored in RGB5A1 format
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) { inline Common::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
u16_le pixel; u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel)); std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F), return {Convert5To8((pixel >> 11) & 0x1F), Convert5To8((pixel >> 6) & 0x1F),
@ -106,9 +106,9 @@ inline Math::Vec4<u8> DecodeRGB5A1(const u8* bytes) {
/** /**
* Decode a color stored in RGBA4 format * Decode a color stored in RGBA4 format
* @param bytes Pointer to encoded source color * @param bytes Pointer to encoded source color
* @return Result color decoded as Math::Vec4<u8> * @return Result color decoded as Common::Vec4<u8>
*/ */
inline Math::Vec4<u8> DecodeRGBA4(const u8* bytes) { inline Common::Vec4<u8> DecodeRGBA4(const u8* bytes) {
u16_le pixel; u16_le pixel;
std::memcpy(&pixel, bytes, sizeof(pixel)); std::memcpy(&pixel, bytes, sizeof(pixel));
return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF), return {Convert4To8((pixel >> 12) & 0xF), Convert4To8((pixel >> 8) & 0xF),
@ -138,9 +138,9 @@ inline u32 DecodeD24(const u8* bytes) {
/** /**
* Decode a depth value and a stencil value stored in D24S8 format * Decode a depth value and a stencil value stored in D24S8 format
* @param bytes Pointer to encoded source values * @param bytes Pointer to encoded source values
* @return Resulting values stored as a Math::Vec2 * @return Resulting values stored as a Common::Vec2
*/ */
inline Math::Vec2<u32> DecodeD24S8(const u8* bytes) { inline Common::Vec2<u32> DecodeD24S8(const u8* bytes) {
return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]}; return {static_cast<u32>((bytes[2] << 16) | (bytes[1] << 8) | bytes[0]), bytes[3]};
} }
@ -149,7 +149,7 @@ inline Math::Vec2<u32> DecodeD24S8(const u8* bytes) {
* @param color Source color to encode * @param color Source color to encode
* @param bytes Destination pointer to store encoded color * @param bytes Destination pointer to store encoded color
*/ */
inline void EncodeRGBA8(const Math::Vec4<u8>& color, u8* bytes) { inline void EncodeRGBA8(const Common::Vec4<u8>& color, u8* bytes) {
bytes[3] = color.r(); bytes[3] = color.r();
bytes[2] = color.g(); bytes[2] = color.g();
bytes[1] = color.b(); bytes[1] = color.b();
@ -161,7 +161,7 @@ inline void EncodeRGBA8(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode * @param color Source color to encode
* @param bytes Destination pointer to store encoded color * @param bytes Destination pointer to store encoded color
*/ */
inline void EncodeRGB8(const Math::Vec4<u8>& color, u8* bytes) { inline void EncodeRGB8(const Common::Vec4<u8>& color, u8* bytes) {
bytes[2] = color.r(); bytes[2] = color.r();
bytes[1] = color.g(); bytes[1] = color.g();
bytes[0] = color.b(); bytes[0] = color.b();
@ -172,7 +172,7 @@ inline void EncodeRGB8(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode * @param color Source color to encode
* @param bytes Destination pointer to store encoded color * @param bytes Destination pointer to store encoded color
*/ */
inline void EncodeRG8(const Math::Vec4<u8>& color, u8* bytes) { inline void EncodeRG8(const Common::Vec4<u8>& color, u8* bytes) {
bytes[1] = color.r(); bytes[1] = color.r();
bytes[0] = color.g(); bytes[0] = color.g();
} }
@ -181,7 +181,7 @@ inline void EncodeRG8(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode * @param color Source color to encode
* @param bytes Destination pointer to store encoded color * @param bytes Destination pointer to store encoded color
*/ */
inline void EncodeRGB565(const Math::Vec4<u8>& color, u8* bytes) { inline void EncodeRGB565(const Common::Vec4<u8>& color, u8* bytes) {
const u16_le data = const u16_le data =
(Convert8To5(color.r()) << 11) | (Convert8To6(color.g()) << 5) | Convert8To5(color.b()); (Convert8To5(color.r()) << 11) | (Convert8To6(color.g()) << 5) | Convert8To5(color.b());
@ -193,7 +193,7 @@ inline void EncodeRGB565(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode * @param color Source color to encode
* @param bytes Destination pointer to store encoded color * @param bytes Destination pointer to store encoded color
*/ */
inline void EncodeRGB5A1(const Math::Vec4<u8>& color, u8* bytes) { inline void EncodeRGB5A1(const Common::Vec4<u8>& color, u8* bytes) {
const u16_le data = (Convert8To5(color.r()) << 11) | (Convert8To5(color.g()) << 6) | const u16_le data = (Convert8To5(color.r()) << 11) | (Convert8To5(color.g()) << 6) |
(Convert8To5(color.b()) << 1) | Convert8To1(color.a()); (Convert8To5(color.b()) << 1) | Convert8To1(color.a());
@ -205,7 +205,7 @@ inline void EncodeRGB5A1(const Math::Vec4<u8>& color, u8* bytes) {
* @param color Source color to encode * @param color Source color to encode
* @param bytes Destination pointer to store encoded color * @param bytes Destination pointer to store encoded color
*/ */
inline void EncodeRGBA4(const Math::Vec4<u8>& color, u8* bytes) { inline void EncodeRGBA4(const Common::Vec4<u8>& color, u8* bytes) {
const u16 data = (Convert8To4(color.r()) << 12) | (Convert8To4(color.g()) << 8) | const u16 data = (Convert8To4(color.r()) << 12) | (Convert8To4(color.g()) << 8) |
(Convert8To4(color.b()) << 4) | Convert8To4(color.a()); (Convert8To4(color.b()) << 4) | Convert8To4(color.a());

View File

@ -7,7 +7,7 @@
#include <cstdlib> #include <cstdlib>
#include <type_traits> #include <type_traits>
namespace MathUtil { namespace Common {
constexpr float PI = 3.14159265f; constexpr float PI = 3.14159265f;
@ -41,4 +41,4 @@ struct Rectangle {
} }
}; };
} // namespace MathUtil } // namespace Common

View File

@ -6,13 +6,13 @@
#include "common/vector_math.h" #include "common/vector_math.h"
namespace Math { namespace Common {
template <typename T> template <typename T>
class Quaternion { class Quaternion {
public: public:
Math::Vec3<T> xyz; Vec3<T> xyz;
T w; T w{};
Quaternion<decltype(-T{})> Inverse() const { Quaternion<decltype(-T{})> Inverse() const {
return {-xyz, w}; return {-xyz, w};
@ -38,12 +38,12 @@ public:
}; };
template <typename T> template <typename T>
auto QuaternionRotate(const Quaternion<T>& q, const Math::Vec3<T>& v) { auto QuaternionRotate(const Quaternion<T>& q, const Vec3<T>& v) {
return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w); return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w);
} }
inline Quaternion<float> MakeQuaternion(const Math::Vec3<float>& axis, float angle) { inline Quaternion<float> MakeQuaternion(const Vec3<float>& axis, float angle) {
return {axis * std::sin(angle / 2), std::cos(angle / 2)}; return {axis * std::sin(angle / 2), std::cos(angle / 2)};
} }
} // namespace Math } // namespace Common

View File

@ -33,7 +33,7 @@
#include <cmath> #include <cmath>
#include <type_traits> #include <type_traits>
namespace Math { namespace Common {
template <typename T> template <typename T>
class Vec2; class Vec2;
@ -702,4 +702,4 @@ constexpr Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw) {
return MakeVec(x, yzw[0], yzw[1], yzw[2]); return MakeVec(x, yzw[0], yzw[1], yzw[2]);
} }
} // namespace Math } // namespace Common

View File

@ -22,12 +22,12 @@ u16 FramebufferLayout::GetScalingRatio() const {
// Finds the largest size subrectangle contained in window area that is confined to the aspect ratio // Finds the largest size subrectangle contained in window area that is confined to the aspect ratio
template <class T> template <class T>
static MathUtil::Rectangle<T> maxRectangle(MathUtil::Rectangle<T> window_area, static Common::Rectangle<T> maxRectangle(Common::Rectangle<T> window_area,
float screen_aspect_ratio) { float screen_aspect_ratio) {
float scale = std::min(static_cast<float>(window_area.GetWidth()), float scale = std::min(static_cast<float>(window_area.GetWidth()),
window_area.GetHeight() / screen_aspect_ratio); window_area.GetHeight() / screen_aspect_ratio);
return MathUtil::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)), return Common::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)),
static_cast<T>(std::round(scale * screen_aspect_ratio))}; static_cast<T>(std::round(scale * screen_aspect_ratio))};
} }
FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height, bool swapped) { FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height, bool swapped) {
@ -36,10 +36,10 @@ FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height, bool swapp
FramebufferLayout res{width, height, true, true, {}, {}}; FramebufferLayout res{width, height, true, true, {}, {}};
// Default layout gives equal screen sizes to the top and bottom screen // Default layout gives equal screen sizes to the top and bottom screen
MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height / 2}; Common::Rectangle<unsigned> screen_window_area{0, 0, width, height / 2};
MathUtil::Rectangle<unsigned> top_screen = Common::Rectangle<unsigned> top_screen =
maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
MathUtil::Rectangle<unsigned> bot_screen = Common::Rectangle<unsigned> bot_screen =
maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
float window_aspect_ratio = static_cast<float>(height) / width; float window_aspect_ratio = static_cast<float>(height) / width;
@ -77,10 +77,10 @@ FramebufferLayout SingleFrameLayout(unsigned width, unsigned height, bool swappe
// so just calculate them both even if the other isn't showing. // so just calculate them both even if the other isn't showing.
FramebufferLayout res{width, height, !swapped, swapped, {}, {}}; FramebufferLayout res{width, height, !swapped, swapped, {}, {}};
MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height}; Common::Rectangle<unsigned> screen_window_area{0, 0, width, height};
MathUtil::Rectangle<unsigned> top_screen = Common::Rectangle<unsigned> top_screen =
maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
MathUtil::Rectangle<unsigned> bot_screen = Common::Rectangle<unsigned> bot_screen =
maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
float window_aspect_ratio = static_cast<float>(height) / width; float window_aspect_ratio = static_cast<float>(height) / width;
@ -116,13 +116,12 @@ FramebufferLayout LargeFrameLayout(unsigned width, unsigned height, bool swapped
float large_screen_aspect_ratio = swapped ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO; float large_screen_aspect_ratio = swapped ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO;
float small_screen_aspect_ratio = swapped ? TOP_SCREEN_ASPECT_RATIO : BOT_SCREEN_ASPECT_RATIO; float small_screen_aspect_ratio = swapped ? TOP_SCREEN_ASPECT_RATIO : BOT_SCREEN_ASPECT_RATIO;
MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height}; Common::Rectangle<unsigned> screen_window_area{0, 0, width, height};
MathUtil::Rectangle<unsigned> total_rect = Common::Rectangle<unsigned> total_rect =
maxRectangle(screen_window_area, emulation_aspect_ratio); maxRectangle(screen_window_area, emulation_aspect_ratio);
MathUtil::Rectangle<unsigned> large_screen = Common::Rectangle<unsigned> large_screen = maxRectangle(total_rect, large_screen_aspect_ratio);
maxRectangle(total_rect, large_screen_aspect_ratio); Common::Rectangle<unsigned> fourth_size_rect = total_rect.Scale(.25f);
MathUtil::Rectangle<unsigned> fourth_size_rect = total_rect.Scale(.25f); Common::Rectangle<unsigned> small_screen =
MathUtil::Rectangle<unsigned> small_screen =
maxRectangle(fourth_size_rect, small_screen_aspect_ratio); maxRectangle(fourth_size_rect, small_screen_aspect_ratio);
if (window_aspect_ratio < emulation_aspect_ratio) { if (window_aspect_ratio < emulation_aspect_ratio) {
@ -149,13 +148,13 @@ FramebufferLayout SideFrameLayout(unsigned width, unsigned height, bool swapped)
const float emulation_aspect_ratio = static_cast<float>(Core::kScreenTopHeight) / const float emulation_aspect_ratio = static_cast<float>(Core::kScreenTopHeight) /
(Core::kScreenTopWidth + Core::kScreenBottomWidth); (Core::kScreenTopWidth + Core::kScreenBottomWidth);
float window_aspect_ratio = static_cast<float>(height) / width; float window_aspect_ratio = static_cast<float>(height) / width;
MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height}; Common::Rectangle<unsigned> screen_window_area{0, 0, width, height};
// Find largest Rectangle that can fit in the window size with the given aspect ratio // Find largest Rectangle that can fit in the window size with the given aspect ratio
MathUtil::Rectangle<unsigned> screen_rect = Common::Rectangle<unsigned> screen_rect =
maxRectangle(screen_window_area, emulation_aspect_ratio); maxRectangle(screen_window_area, emulation_aspect_ratio);
// Find sizes of top and bottom screen // Find sizes of top and bottom screen
MathUtil::Rectangle<unsigned> top_screen = maxRectangle(screen_rect, TOP_SCREEN_ASPECT_RATIO); Common::Rectangle<unsigned> top_screen = maxRectangle(screen_rect, TOP_SCREEN_ASPECT_RATIO);
MathUtil::Rectangle<unsigned> bot_screen = maxRectangle(screen_rect, BOT_SCREEN_ASPECT_RATIO); Common::Rectangle<unsigned> bot_screen = maxRectangle(screen_rect, BOT_SCREEN_ASPECT_RATIO);
if (window_aspect_ratio < emulation_aspect_ratio) { if (window_aspect_ratio < emulation_aspect_ratio) {
// Apply borders to the left and right sides of the window. // Apply borders to the left and right sides of the window.
@ -180,10 +179,10 @@ FramebufferLayout CustomFrameLayout(unsigned width, unsigned height) {
FramebufferLayout res{width, height, true, true, {}, {}}; FramebufferLayout res{width, height, true, true, {}, {}};
MathUtil::Rectangle<unsigned> top_screen{ Common::Rectangle<unsigned> top_screen{
Settings::values.custom_top_left, Settings::values.custom_top_top, Settings::values.custom_top_left, Settings::values.custom_top_top,
Settings::values.custom_top_right, Settings::values.custom_top_bottom}; Settings::values.custom_top_right, Settings::values.custom_top_bottom};
MathUtil::Rectangle<unsigned> bot_screen{ Common::Rectangle<unsigned> bot_screen{
Settings::values.custom_bottom_left, Settings::values.custom_bottom_top, Settings::values.custom_bottom_left, Settings::values.custom_bottom_top,
Settings::values.custom_bottom_right, Settings::values.custom_bottom_bottom}; Settings::values.custom_bottom_right, Settings::values.custom_bottom_bottom};

View File

@ -14,8 +14,8 @@ struct FramebufferLayout {
unsigned height; unsigned height;
bool top_screen_enabled; bool top_screen_enabled;
bool bottom_screen_enabled; bool bottom_screen_enabled;
MathUtil::Rectangle<unsigned> top_screen; Common::Rectangle<unsigned> top_screen;
MathUtil::Rectangle<unsigned> bottom_screen; Common::Rectangle<unsigned> bottom_screen;
/** /**
* Returns the ration of pixel size of the top screen, compared to the native size of the 3DS * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS

View File

@ -124,7 +124,7 @@ using AnalogDevice = InputDevice<std::tuple<float, float>>;
* Orientation is determined by right-hand rule. * Orientation is determined by right-hand rule.
* Units: deg/sec * Units: deg/sec
*/ */
using MotionDevice = InputDevice<std::tuple<Math::Vec3<float>, Math::Vec3<float>>>; using MotionDevice = InputDevice<std::tuple<Common::Vec3<float>, Common::Vec3<float>>>;
/** /**
* A touch device is an input device that returns a tuple of two floats and a bool. The floats are * A touch device is an input device that returns a tuple of two floats and a bool. The floats are

View File

@ -179,7 +179,7 @@ void Module::UpdateAccelerometerCallback(u64 userdata, s64 cycles_late) {
mem->accelerometer.index = next_accelerometer_index; mem->accelerometer.index = next_accelerometer_index;
next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
Math::Vec3<float> accel; Common::Vec3<float> accel;
std::tie(accel, std::ignore) = motion_device->GetStatus(); std::tie(accel, std::ignore) = motion_device->GetStatus();
accel *= accelerometer_coef; accel *= accelerometer_coef;
// TODO(wwylele): do a time stretch like the one in UpdateGyroscopeCallback // TODO(wwylele): do a time stretch like the one in UpdateGyroscopeCallback
@ -226,7 +226,7 @@ void Module::UpdateGyroscopeCallback(u64 userdata, s64 cycles_late) {
GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
Math::Vec3<float> gyro; Common::Vec3<float> gyro;
std::tie(std::ignore, gyro) = motion_device->GetStatus(); std::tie(std::ignore, gyro) = motion_device->GetStatus();
double stretch = system.perf_stats.GetLastFrameTimeScale(); double stretch = system.perf_stats.GetLastFrameTimeScale();
gyro *= gyroscope_coef * static_cast<float>(stretch); gyro *= gyroscope_coef * static_cast<float>(stretch);

View File

@ -48,7 +48,7 @@ inline void Read(T& var, const u32 raw_addr) {
var = g_regs[addr / 4]; var = g_regs[addr / 4];
} }
static Math::Vec4<u8> DecodePixel(Regs::PixelFormat input_format, const u8* src_pixel) { static Common::Vec4<u8> DecodePixel(Regs::PixelFormat input_format, const u8* src_pixel) {
switch (input_format) { switch (input_format) {
case Regs::PixelFormat::RGBA8: case Regs::PixelFormat::RGBA8:
return Color::DecodeRGBA8(src_pixel); return Color::DecodeRGBA8(src_pixel);
@ -196,7 +196,7 @@ static void DisplayTransfer(const Regs::DisplayTransferConfig& config) {
for (u32 y = 0; y < output_height; ++y) { for (u32 y = 0; y < output_height; ++y) {
for (u32 x = 0; x < output_width; ++x) { for (u32 x = 0; x < output_width; ++x) {
Math::Vec4<u8> src_color; Common::Vec4<u8> src_color;
// Calculate the [x,y] position of the input image // Calculate the [x,y] position of the input image
// based on the current output position and the scale // based on the current output position and the scale
@ -259,15 +259,15 @@ static void DisplayTransfer(const Regs::DisplayTransferConfig& config) {
const u8* src_pixel = src_pointer + src_offset; const u8* src_pixel = src_pointer + src_offset;
src_color = DecodePixel(config.input_format, src_pixel); src_color = DecodePixel(config.input_format, src_pixel);
if (config.scaling == config.ScaleX) { if (config.scaling == config.ScaleX) {
Math::Vec4<u8> pixel = Common::Vec4<u8> pixel =
DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel);
src_color = ((src_color + pixel) / 2).Cast<u8>(); src_color = ((src_color + pixel) / 2).Cast<u8>();
} else if (config.scaling == config.ScaleXY) { } else if (config.scaling == config.ScaleXY) {
Math::Vec4<u8> pixel1 = Common::Vec4<u8> pixel1 =
DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel); DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel);
Math::Vec4<u8> pixel2 = Common::Vec4<u8> pixel2 =
DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel); DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel);
Math::Vec4<u8> pixel3 = Common::Vec4<u8> pixel3 =
DecodePixel(config.input_format, src_pixel + 3 * src_bytes_per_pixel); DecodePixel(config.input_format, src_pixel + 3 * src_bytes_per_pixel);
src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>();
} }

View File

@ -110,7 +110,7 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data
u8* unit_end = output + buf.transfer_unit; u8* unit_end = output + buf.transfer_unit;
while (output < unit_end) { while (output < unit_end) {
u32 color = *input++; u32 color = *input++;
Math::Vec4<u8> col_vec{(u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha}; Common::Vec4<u8> col_vec{(u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha};
switch (output_format) { switch (output_format) {
case OutputFormat::RGBA8: case OutputFormat::RGBA8:

View File

@ -33,12 +33,12 @@ public:
} }
void BeginTilt(int x, int y) { void BeginTilt(int x, int y) {
mouse_origin = Math::MakeVec(x, y); mouse_origin = Common::MakeVec(x, y);
is_tilting = true; is_tilting = true;
} }
void Tilt(int x, int y) { void Tilt(int x, int y) {
auto mouse_move = Math::MakeVec(x, y) - mouse_origin; auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
if (is_tilting) { if (is_tilting) {
std::lock_guard<std::mutex> guard(tilt_mutex); std::lock_guard<std::mutex> guard(tilt_mutex);
if (mouse_move.x == 0 && mouse_move.y == 0) { if (mouse_move.x == 0 && mouse_move.y == 0) {
@ -46,7 +46,7 @@ public:
} else { } else {
tilt_direction = mouse_move.Cast<float>(); tilt_direction = mouse_move.Cast<float>();
tilt_angle = std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, tilt_angle = std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f,
MathUtil::PI * this->tilt_clamp / 180.0f); Common::PI * this->tilt_clamp / 180.0f);
} }
} }
} }
@ -57,7 +57,7 @@ public:
is_tilting = false; is_tilting = false;
} }
std::tuple<Math::Vec3<float>, Math::Vec3<float>> GetStatus() { std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() {
std::lock_guard<std::mutex> guard(status_mutex); std::lock_guard<std::mutex> guard(status_mutex);
return status; return status;
} }
@ -67,10 +67,10 @@ private:
const std::chrono::steady_clock::duration update_duration; const std::chrono::steady_clock::duration update_duration;
const float sensitivity; const float sensitivity;
Math::Vec2<int> mouse_origin; Common::Vec2<int> mouse_origin;
std::mutex tilt_mutex; std::mutex tilt_mutex;
Math::Vec2<float> tilt_direction; Common::Vec2<float> tilt_direction;
float tilt_angle = 0; float tilt_angle = 0;
float tilt_clamp = 90; float tilt_clamp = 90;
@ -78,7 +78,7 @@ private:
Common::Event shutdown_event; Common::Event shutdown_event;
std::tuple<Math::Vec3<float>, Math::Vec3<float>> status; std::tuple<Common::Vec3<float>, Common::Vec3<float>> status;
std::mutex status_mutex; std::mutex status_mutex;
// Note: always keep the thread declaration at the end so that other objects are initialized // Note: always keep the thread declaration at the end so that other objects are initialized
@ -87,8 +87,8 @@ private:
void MotionEmuThread() { void MotionEmuThread() {
auto update_time = std::chrono::steady_clock::now(); auto update_time = std::chrono::steady_clock::now();
Math::Quaternion<float> q = MakeQuaternion(Math::Vec3<float>(), 0); Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
Math::Quaternion<float> old_q; Common::Quaternion<float> old_q;
while (!shutdown_event.WaitUntil(update_time)) { while (!shutdown_event.WaitUntil(update_time)) {
update_time += update_duration; update_time += update_duration;
@ -98,18 +98,18 @@ private:
std::lock_guard<std::mutex> guard(tilt_mutex); std::lock_guard<std::mutex> guard(tilt_mutex);
// Find the quaternion describing current 3DS tilting // Find the quaternion describing current 3DS tilting
q = MakeQuaternion(Math::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), q = Common::MakeQuaternion(
tilt_angle); Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle);
} }
auto inv_q = q.Inverse(); auto inv_q = q.Inverse();
// Set the gravity vector in world space // Set the gravity vector in world space
auto gravity = Math::MakeVec(0.0f, -1.0f, 0.0f); auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
// Find the angular rate vector in world space // Find the angular rate vector in world space
auto angular_rate = ((q - old_q) * inv_q).xyz * 2; auto angular_rate = ((q - old_q) * inv_q).xyz * 2;
angular_rate *= 1000 / update_millisecond / MathUtil::PI * 180; angular_rate *= 1000 / update_millisecond / Common::PI * 180;
// Transform the two vectors from world space to 3DS space // Transform the two vectors from world space to 3DS space
gravity = QuaternionRotate(inv_q, gravity); gravity = QuaternionRotate(inv_q, gravity);
@ -133,7 +133,7 @@ public:
device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity, tilt_clamp); device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity, tilt_clamp);
} }
std::tuple<Math::Vec3<float>, Math::Vec3<float>> GetStatus() const override { std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
return device->GetStatus(); return device->GetStatus();
} }

View File

@ -162,8 +162,8 @@ void Client::OnPadData(Response::PadData data) {
// Due to differences between the 3ds and cemuhookudp motion directions, we need to invert // Due to differences between the 3ds and cemuhookudp motion directions, we need to invert
// accel.x and accel.z and also invert pitch and yaw. See // accel.x and accel.z and also invert pitch and yaw. See
// https://github.com/citra-emu/citra/pull/4049 for more details on gyro/accel // https://github.com/citra-emu/citra/pull/4049 for more details on gyro/accel
Math::Vec3f accel = Math::MakeVec<float>(-data.accel.x, data.accel.y, -data.accel.z); Common::Vec3f accel = Common::MakeVec<float>(-data.accel.x, data.accel.y, -data.accel.z);
Math::Vec3f gyro = Math::MakeVec<float>(-data.gyro.pitch, -data.gyro.yaw, data.gyro.roll); Common::Vec3f gyro = Common::MakeVec<float>(-data.gyro.pitch, -data.gyro.yaw, data.gyro.roll);
{ {
std::lock_guard<std::mutex> guard(status->update_mutex); std::lock_guard<std::mutex> guard(status->update_mutex);

View File

@ -31,7 +31,7 @@ struct Version;
struct DeviceStatus { struct DeviceStatus {
std::mutex update_mutex; std::mutex update_mutex;
std::tuple<Math::Vec3<float>, Math::Vec3<float>> motion_status; std::tuple<Common::Vec3<float>, Common::Vec3<float>> motion_status;
std::tuple<float, float, bool> touch_status; std::tuple<float, float, bool> touch_status;
// calibration data for scaling the device's touch area to 3ds // calibration data for scaling the device's touch area to 3ds

View File

@ -26,7 +26,7 @@ private:
class UDPMotionDevice final : public Input::MotionDevice { class UDPMotionDevice final : public Input::MotionDevice {
public: public:
explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {} explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
std::tuple<Math::Vec3<float>, Math::Vec3<float>> GetStatus() const { std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const {
std::lock_guard<std::mutex> guard(status->update_mutex); std::lock_guard<std::mutex> guard(status->update_mutex);
return status->motion_status; return status->motion_status;
} }

View File

@ -63,7 +63,7 @@ static void WriteUniformBoolReg(Shader::ShaderSetup& setup, u32 value) {
} }
static void WriteUniformIntReg(Shader::ShaderSetup& setup, unsigned index, static void WriteUniformIntReg(Shader::ShaderSetup& setup, unsigned index,
const Math::Vec4<u8>& values) { const Common::Vec4<u8>& values) {
ASSERT(index < setup.uniforms.i.size()); ASSERT(index < setup.uniforms.i.size());
setup.uniforms.i[index] = values; setup.uniforms.i[index] = values;
LOG_TRACE(HW_GPU, "Set {} integer uniform {} to {:02x} {:02x} {:02x} {:02x}", LOG_TRACE(HW_GPU, "Set {} integer uniform {} to {:02x} {:02x} {:02x} {:02x}",
@ -186,7 +186,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
break; break;
} }
Math::Vec4<float24> attribute; Common::Vec4<float24> attribute;
// NOTE: The destination component order indeed is "backwards" // NOTE: The destination component order indeed is "backwards"
attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8); attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8);
@ -447,7 +447,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
unsigned index = (id - PICA_REG_INDEX_WORKAROUND(gs.int_uniforms[0], 0x281)); unsigned index = (id - PICA_REG_INDEX_WORKAROUND(gs.int_uniforms[0], 0x281));
auto values = regs.gs.int_uniforms[index]; auto values = regs.gs.int_uniforms[index];
WriteUniformIntReg(g_state.gs, index, WriteUniformIntReg(g_state.gs, index,
Math::Vec4<u8>(values.x, values.y, values.z, values.w)); Common::Vec4<u8>(values.x, values.y, values.z, values.w));
break; break;
} }
@ -515,7 +515,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
unsigned index = (id - PICA_REG_INDEX_WORKAROUND(vs.int_uniforms[0], 0x2b1)); unsigned index = (id - PICA_REG_INDEX_WORKAROUND(vs.int_uniforms[0], 0x2b1));
auto values = regs.vs.int_uniforms[index]; auto values = regs.vs.int_uniforms[index];
WriteUniformIntReg(g_state.vs, index, WriteUniformIntReg(g_state.vs, index,
Math::Vec4<u8>(values.x, values.y, values.z, values.w)); Common::Vec4<u8>(values.x, values.y, values.z, values.w));
break; break;
} }

View File

@ -76,8 +76,8 @@ private:
const Regs& regs; const Regs& regs;
Shader::GSUnitState& unit; Shader::GSUnitState& unit;
Shader::AttributeBuffer attribute_buffer; Shader::AttributeBuffer attribute_buffer;
Math::Vec4<float24>* buffer_cur; Common::Vec4<float24>* buffer_cur;
Math::Vec4<float24>* buffer_end; Common::Vec4<float24>* buffer_end;
unsigned int vs_output_num; unsigned int vs_output_num;
}; };
@ -106,7 +106,7 @@ public:
// The number of vertex input is put to the uniform register // The number of vertex input is put to the uniform register
float24 vertex_num = float24::FromFloat32(static_cast<float>(val)); float24 vertex_num = float24::FromFloat32(static_cast<float>(val));
setup.uniforms.f[0] = Math::MakeVec(vertex_num, vertex_num, vertex_num, vertex_num); setup.uniforms.f[0] = Common::MakeVec(vertex_num, vertex_num, vertex_num, vertex_num);
// The second uniform register and so on are used for receiving input vertices // The second uniform register and so on are used for receiving input vertices
buffer_cur = setup.uniforms.f + 1; buffer_cur = setup.uniforms.f + 1;
@ -142,7 +142,7 @@ private:
Shader::ShaderSetup& setup; Shader::ShaderSetup& setup;
unsigned int main_vertex_num; unsigned int main_vertex_num;
unsigned int total_vertex_num; unsigned int total_vertex_num;
Math::Vec4<float24>* buffer_cur; Common::Vec4<float24>* buffer_cur;
unsigned int vs_output_num; unsigned int vs_output_num;
}; };
@ -186,9 +186,9 @@ public:
private: private:
const Regs& regs; const Regs& regs;
Shader::ShaderSetup& setup; Shader::ShaderSetup& setup;
Math::Vec4<float24>* buffer_begin; Common::Vec4<float24>* buffer_begin;
Math::Vec4<float24>* buffer_cur; Common::Vec4<float24>* buffer_cur;
Math::Vec4<float24>* buffer_end; Common::Vec4<float24>* buffer_end;
unsigned int vs_output_num; unsigned int vs_output_num;
}; };

View File

@ -56,7 +56,7 @@ struct State {
BitField<16, 8, u32> b; BitField<16, 8, u32> b;
BitField<24, 8, u32> a; BitField<24, 8, u32> a;
Math::Vec4<u8> ToVector() const { Common::Vec4<u8> ToVector() const {
return {static_cast<u8>(r), static_cast<u8>(g), static_cast<u8>(b), return {static_cast<u8>(r), static_cast<u8>(g), static_cast<u8>(b),
static_cast<u8>(a)}; static_cast<u8>(a)};
} }
@ -69,8 +69,8 @@ struct State {
BitField<16, 8, s32> b; BitField<16, 8, s32> b;
BitField<24, 8, s32> a; BitField<24, 8, s32> a;
Math::Vec4<s32> ToVector() const { Common::Vec4<s32> ToVector() const {
return Math::Vec4<s32>{r, g, b, a} * 2; return Common::Vec4<s32>{r, g, b, a} * 2;
} }
}; };

View File

@ -90,10 +90,10 @@ struct LightingRegs {
BitField<10, 10, u32> g; BitField<10, 10, u32> g;
BitField<20, 10, u32> r; BitField<20, 10, u32> r;
Math::Vec3f ToVec3f() const { Common::Vec3f ToVec3f() const {
// These fields are 10 bits wide, however 255 corresponds to 1.0f for each color // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color
// component // component
return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); return Common::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f);
} }
}; };

View File

@ -36,7 +36,7 @@ struct RasterizerRegs {
BitField<0, 1, u32> clip_enable; BitField<0, 1, u32> clip_enable;
BitField<0, 24, u32> clip_coef[4]; // float24 BitField<0, 24, u32> clip_coef[4]; // float24
Math::Vec4<float24> GetClipCoef() const { Common::Vec4<float24> GetClipCoef() const {
return {float24::FromRaw(clip_coef[0]), float24::FromRaw(clip_coef[1]), return {float24::FromRaw(clip_coef[0]), float24::FromRaw(clip_coef[1]),
float24::FromRaw(clip_coef[2]), float24::FromRaw(clip_coef[3])}; float24::FromRaw(clip_coef[2]), float24::FromRaw(clip_coef[3])};
} }

View File

@ -224,11 +224,11 @@ void RasterizerOpenGL::SyncEntireState() {
* Fortunately however, the 3DS hardware happens to also use this exact same logic to work around * Fortunately however, the 3DS hardware happens to also use this exact same logic to work around
* these issues, making this basic implementation actually more accurate to the hardware. * these issues, making this basic implementation actually more accurate to the hardware.
*/ */
static bool AreQuaternionsOpposite(Math::Vec4<Pica::float24> qa, Math::Vec4<Pica::float24> qb) { static bool AreQuaternionsOpposite(Common::Vec4<Pica::float24> qa, Common::Vec4<Pica::float24> qb) {
Math::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()}; Common::Vec4f a{qa.x.ToFloat32(), qa.y.ToFloat32(), qa.z.ToFloat32(), qa.w.ToFloat32()};
Math::Vec4f b{qb.x.ToFloat32(), qb.y.ToFloat32(), qb.z.ToFloat32(), qb.w.ToFloat32()}; Common::Vec4f b{qb.x.ToFloat32(), qb.y.ToFloat32(), qb.z.ToFloat32(), qb.w.ToFloat32()};
return (Math::Dot(a, b) < 0.f); return (Common::Dot(a, b) < 0.f);
} }
void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0, void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0,
@ -522,7 +522,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
(write_depth_fb || regs.framebuffer.output_merger.depth_test_enable != 0 || (write_depth_fb || regs.framebuffer.output_merger.depth_test_enable != 0 ||
(has_stencil && state.stencil.test_enabled)); (has_stencil && state.stencil.test_enabled));
MathUtil::Rectangle<s32> viewport_rect_unscaled{ Common::Rectangle<s32> viewport_rect_unscaled{
// These registers hold half-width and half-height, so must be multiplied by 2 // These registers hold half-width and half-height, so must be multiplied by 2
regs.rasterizer.viewport_corner.x, // left regs.rasterizer.viewport_corner.x, // left
regs.rasterizer.viewport_corner.y + // top regs.rasterizer.viewport_corner.y + // top
@ -536,7 +536,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
Surface color_surface; Surface color_surface;
Surface depth_surface; Surface depth_surface;
MathUtil::Rectangle<u32> surfaces_rect; Common::Rectangle<u32> surfaces_rect;
std::tie(color_surface, depth_surface, surfaces_rect) = std::tie(color_surface, depth_surface, surfaces_rect) =
res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect_unscaled); res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect_unscaled);
@ -544,7 +544,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
? color_surface->res_scale ? color_surface->res_scale
: (depth_surface == nullptr ? 1u : depth_surface->res_scale); : (depth_surface == nullptr ? 1u : depth_surface->res_scale);
MathUtil::Rectangle<u32> draw_rect{ Common::Rectangle<u32> draw_rect{
static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) +
viewport_rect_unscaled.left * res_scale, viewport_rect_unscaled.left * res_scale,
surfaces_rect.left, surfaces_rect.right)), // Left surfaces_rect.left, surfaces_rect.right)), // Left
@ -841,9 +841,9 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
} }
// Mark framebuffer surfaces as dirty // Mark framebuffer surfaces as dirty
MathUtil::Rectangle<u32> draw_rect_unscaled{ Common::Rectangle<u32> draw_rect_unscaled{draw_rect.left / res_scale, draw_rect.top / res_scale,
draw_rect.left / res_scale, draw_rect.top / res_scale, draw_rect.right / res_scale, draw_rect.right / res_scale,
draw_rect.bottom / res_scale}; draw_rect.bottom / res_scale};
if (color_surface != nullptr && write_color_fb) { if (color_surface != nullptr && write_color_fb) {
auto interval = color_surface->GetSubRectInterval(draw_rect_unscaled); auto interval = color_surface->GetSubRectInterval(draw_rect_unscaled);
@ -1392,7 +1392,7 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe
dst_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.output_format); dst_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.output_format);
dst_params.UpdateParams(); dst_params.UpdateParams();
MathUtil::Rectangle<u32> src_rect; Common::Rectangle<u32> src_rect;
Surface src_surface; Surface src_surface;
std::tie(src_surface, src_rect) = std::tie(src_surface, src_rect) =
res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true); res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true);
@ -1401,7 +1401,7 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe
dst_params.res_scale = src_surface->res_scale; dst_params.res_scale = src_surface->res_scale;
MathUtil::Rectangle<u32> dst_rect; Common::Rectangle<u32> dst_rect;
Surface dst_surface; Surface dst_surface;
std::tie(dst_surface, dst_rect) = std::tie(dst_surface, dst_rect) =
res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, false); res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, false);
@ -1461,7 +1461,7 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon
src_params.size = ((src_params.height - 1) * src_params.stride) + src_params.width; src_params.size = ((src_params.height - 1) * src_params.stride) + src_params.width;
src_params.end = src_params.addr + src_params.size; src_params.end = src_params.addr + src_params.size;
MathUtil::Rectangle<u32> src_rect; Common::Rectangle<u32> src_rect;
Surface src_surface; Surface src_surface;
std::tie(src_surface, src_rect) = res_cache.GetTexCopySurface(src_params); std::tie(src_surface, src_rect) = res_cache.GetTexCopySurface(src_params);
if (src_surface == nullptr) { if (src_surface == nullptr) {
@ -1486,7 +1486,7 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon
// Since we are going to invalidate the gap if there is one, we will have to load it first // Since we are going to invalidate the gap if there is one, we will have to load it first
const bool load_gap = output_gap != 0; const bool load_gap = output_gap != 0;
MathUtil::Rectangle<u32> dst_rect; Common::Rectangle<u32> dst_rect;
Surface dst_surface; Surface dst_surface;
std::tie(dst_surface, dst_rect) = std::tie(dst_surface, dst_rect) =
res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, load_gap); res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, load_gap);
@ -1532,7 +1532,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
src_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.color_format); src_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.color_format);
src_params.UpdateParams(); src_params.UpdateParams();
MathUtil::Rectangle<u32> src_rect; Common::Rectangle<u32> src_rect;
Surface src_surface; Surface src_surface;
std::tie(src_surface, src_rect) = std::tie(src_surface, src_rect) =
res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true); res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true);
@ -1544,7 +1544,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
u32 scaled_width = src_surface->GetScaledWidth(); u32 scaled_width = src_surface->GetScaledWidth();
u32 scaled_height = src_surface->GetScaledHeight(); u32 scaled_height = src_surface->GetScaledHeight();
screen_info.display_texcoords = MathUtil::Rectangle<float>( screen_info.display_texcoords = Common::Rectangle<float>(
(float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width, (float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width,
(float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width); (float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width);

View File

@ -347,8 +347,8 @@ static void AllocateTextureCube(GLuint texture, const FormatTuple& format_tuple,
cur_state.Apply(); cur_state.Apply();
} }
static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, static bool BlitTextures(GLuint src_tex, const Common::Rectangle<u32>& src_rect, GLuint dst_tex,
const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, const Common::Rectangle<u32>& dst_rect, SurfaceType type,
GLuint read_fb_handle, GLuint draw_fb_handle) { GLuint read_fb_handle, GLuint draw_fb_handle) {
OpenGLState prev_state = OpenGLState::GetCurState(); OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
@ -407,7 +407,7 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rec
} }
static bool FillSurface(const Surface& surface, const u8* fill_data, static bool FillSurface(const Surface& surface, const u8* fill_data,
const MathUtil::Rectangle<u32>& fill_rect, GLuint draw_fb_handle) { const Common::Rectangle<u32>& fill_rect, GLuint draw_fb_handle) {
OpenGLState prev_state = OpenGLState::GetCurState(); OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
@ -431,7 +431,7 @@ static bool FillSurface(const Surface& surface, const u8* fill_data,
Pica::Texture::TextureInfo tex_info{}; Pica::Texture::TextureInfo tex_info{};
tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface->pixel_format); tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface->pixel_format);
Math::Vec4<u8> color = Pica::Texture::LookupTexture(fill_data, 0, 0, tex_info); Common::Vec4<u8> color = Pica::Texture::LookupTexture(fill_data, 0, 0, tex_info);
std::array<GLfloat, 4> color_values = {color.x / 255.f, color.y / 255.f, color.z / 255.f, std::array<GLfloat, 4> color_values = {color.x / 255.f, color.y / 255.f, color.z / 255.f,
color.w / 255.f}; color.w / 255.f};
@ -511,7 +511,7 @@ SurfaceParams SurfaceParams::FromInterval(SurfaceInterval interval) const {
return params; return params;
} }
SurfaceInterval SurfaceParams::GetSubRectInterval(MathUtil::Rectangle<u32> unscaled_rect) const { SurfaceInterval SurfaceParams::GetSubRectInterval(Common::Rectangle<u32> unscaled_rect) const {
if (unscaled_rect.GetHeight() == 0 || unscaled_rect.GetWidth() == 0) { if (unscaled_rect.GetHeight() == 0 || unscaled_rect.GetWidth() == 0) {
return {}; return {};
} }
@ -534,24 +534,24 @@ SurfaceInterval SurfaceParams::GetSubRectInterval(MathUtil::Rectangle<u32> unsca
return {addr + BytesInPixels(pixel_offset), addr + BytesInPixels(pixel_offset + pixels)}; return {addr + BytesInPixels(pixel_offset), addr + BytesInPixels(pixel_offset + pixels)};
} }
MathUtil::Rectangle<u32> SurfaceParams::GetSubRect(const SurfaceParams& sub_surface) const { Common::Rectangle<u32> SurfaceParams::GetSubRect(const SurfaceParams& sub_surface) const {
const u32 begin_pixel_index = PixelsInBytes(sub_surface.addr - addr); const u32 begin_pixel_index = PixelsInBytes(sub_surface.addr - addr);
if (is_tiled) { if (is_tiled) {
const int x0 = (begin_pixel_index % (stride * 8)) / 8; const int x0 = (begin_pixel_index % (stride * 8)) / 8;
const int y0 = (begin_pixel_index / (stride * 8)) * 8; const int y0 = (begin_pixel_index / (stride * 8)) * 8;
// Top to bottom // Top to bottom
return MathUtil::Rectangle<u32>(x0, height - y0, x0 + sub_surface.width, return Common::Rectangle<u32>(x0, height - y0, x0 + sub_surface.width,
height - (y0 + sub_surface.height)); height - (y0 + sub_surface.height));
} }
const int x0 = begin_pixel_index % stride; const int x0 = begin_pixel_index % stride;
const int y0 = begin_pixel_index / stride; const int y0 = begin_pixel_index / stride;
// Bottom to top // Bottom to top
return MathUtil::Rectangle<u32>(x0, y0 + sub_surface.height, x0 + sub_surface.width, y0); return Common::Rectangle<u32>(x0, y0 + sub_surface.height, x0 + sub_surface.width, y0);
} }
MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& sub_surface) const { Common::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& sub_surface) const {
auto rect = GetSubRect(sub_surface); auto rect = GetSubRect(sub_surface);
rect.left = rect.left * res_scale; rect.left = rect.left * res_scale;
rect.right = rect.right * res_scale; rect.right = rect.right * res_scale;
@ -819,7 +819,7 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) {
} }
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint read_fb_handle,
GLuint draw_fb_handle) { GLuint draw_fb_handle) {
if (type == SurfaceType::Fill) if (type == SurfaceType::Fill)
return; return;
@ -883,7 +883,7 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
} }
MICROPROFILE_DEFINE(OpenGL_TextureDL, "OpenGL", "Texture Download", MP_RGB(128, 192, 64)); MICROPROFILE_DEFINE(OpenGL_TextureDL, "OpenGL", "Texture Download", MP_RGB(128, 192, 64));
void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, void CachedSurface::DownloadGLTexture(const Common::Rectangle<u32>& rect, GLuint read_fb_handle,
GLuint draw_fb_handle) { GLuint draw_fb_handle) {
if (type == SurfaceType::Fill) if (type == SurfaceType::Fill)
return; return;
@ -918,7 +918,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
OGLTexture unscaled_tex; OGLTexture unscaled_tex;
unscaled_tex.Create(); unscaled_tex.Create();
MathUtil::Rectangle<u32> unscaled_tex_rect{0, rect.GetHeight(), rect.GetWidth(), 0}; Common::Rectangle<u32> unscaled_tex_rect{0, rect.GetHeight(), rect.GetWidth(), 0};
AllocateSurfaceTexture(unscaled_tex.handle, tuple, rect.GetWidth(), rect.GetHeight()); AllocateSurfaceTexture(unscaled_tex.handle, tuple, rect.GetWidth(), rect.GetHeight());
BlitTextures(texture.handle, scaled_rect, unscaled_tex.handle, unscaled_tex_rect, type, BlitTextures(texture.handle, scaled_rect, unscaled_tex.handle, unscaled_tex_rect, type,
read_fb_handle, draw_fb_handle); read_fb_handle, draw_fb_handle);
@ -1122,9 +1122,9 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
MICROPROFILE_DEFINE(OpenGL_BlitSurface, "OpenGL", "BlitSurface", MP_RGB(128, 192, 64)); MICROPROFILE_DEFINE(OpenGL_BlitSurface, "OpenGL", "BlitSurface", MP_RGB(128, 192, 64));
bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface, bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface,
const MathUtil::Rectangle<u32>& src_rect, const Common::Rectangle<u32>& src_rect,
const Surface& dst_surface, const Surface& dst_surface,
const MathUtil::Rectangle<u32>& dst_rect) { const Common::Rectangle<u32>& dst_rect) {
MICROPROFILE_SCOPE(OpenGL_BlitSurface); MICROPROFILE_SCOPE(OpenGL_BlitSurface);
if (!SurfaceParams::CheckFormatsBlittable(src_surface->pixel_format, dst_surface->pixel_format)) if (!SurfaceParams::CheckFormatsBlittable(src_surface->pixel_format, dst_surface->pixel_format))
@ -1138,9 +1138,9 @@ bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface,
} }
void RasterizerCacheOpenGL::ConvertD24S8toABGR(GLuint src_tex, void RasterizerCacheOpenGL::ConvertD24S8toABGR(GLuint src_tex,
const MathUtil::Rectangle<u32>& src_rect, const Common::Rectangle<u32>& src_rect,
GLuint dst_tex, GLuint dst_tex,
const MathUtil::Rectangle<u32>& dst_rect) { const Common::Rectangle<u32>& dst_rect) {
OpenGLState prev_state = OpenGLState::GetCurState(); OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
@ -1247,7 +1247,7 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams&
ScaleMatch match_res_scale, ScaleMatch match_res_scale,
bool load_if_create) { bool load_if_create) {
if (params.addr == 0 || params.height * params.width == 0) { if (params.addr == 0 || params.height * params.width == 0) {
return std::make_tuple(nullptr, MathUtil::Rectangle<u32>{}); return std::make_tuple(nullptr, Common::Rectangle<u32>{});
} }
// Attempt to find encompassing surface // Attempt to find encompassing surface
@ -1340,7 +1340,7 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::Texture::TextureInf
if (info.width % 8 != 0 || info.height % 8 != 0) { if (info.width % 8 != 0 || info.height % 8 != 0) {
Surface src_surface; Surface src_surface;
MathUtil::Rectangle<u32> rect; Common::Rectangle<u32> rect;
std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
params.res_scale = src_surface->res_scale; params.res_scale = src_surface->res_scale;
@ -1447,7 +1447,7 @@ const CachedTextureCube& RasterizerCacheOpenGL::GetTextureCube(const TextureCube
} }
SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport_rect) { bool using_color_fb, bool using_depth_fb, const Common::Rectangle<s32>& viewport_rect) {
const auto& regs = Pica::g_state.regs; const auto& regs = Pica::g_state.regs;
const auto& config = regs.framebuffer.framebuffer; const auto& config = regs.framebuffer.framebuffer;
@ -1461,7 +1461,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
texture_cube_cache.clear(); texture_cube_cache.clear();
} }
MathUtil::Rectangle<u32> viewport_clamped{ Common::Rectangle<u32> viewport_clamped{
static_cast<u32>(std::clamp(viewport_rect.left, 0, static_cast<s32>(config.GetWidth()))), static_cast<u32>(std::clamp(viewport_rect.left, 0, static_cast<s32>(config.GetWidth()))),
static_cast<u32>(std::clamp(viewport_rect.top, 0, static_cast<s32>(config.GetHeight()))), static_cast<u32>(std::clamp(viewport_rect.top, 0, static_cast<s32>(config.GetHeight()))),
static_cast<u32>(std::clamp(viewport_rect.right, 0, static_cast<s32>(config.GetWidth()))), static_cast<u32>(std::clamp(viewport_rect.right, 0, static_cast<s32>(config.GetWidth()))),
@ -1495,19 +1495,19 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
using_depth_fb = false; using_depth_fb = false;
} }
MathUtil::Rectangle<u32> color_rect{}; Common::Rectangle<u32> color_rect{};
Surface color_surface = nullptr; Surface color_surface = nullptr;
if (using_color_fb) if (using_color_fb)
std::tie(color_surface, color_rect) = std::tie(color_surface, color_rect) =
GetSurfaceSubRect(color_params, ScaleMatch::Exact, false); GetSurfaceSubRect(color_params, ScaleMatch::Exact, false);
MathUtil::Rectangle<u32> depth_rect{}; Common::Rectangle<u32> depth_rect{};
Surface depth_surface = nullptr; Surface depth_surface = nullptr;
if (using_depth_fb) if (using_depth_fb)
std::tie(depth_surface, depth_rect) = std::tie(depth_surface, depth_rect) =
GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false); GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false);
MathUtil::Rectangle<u32> fb_rect{}; Common::Rectangle<u32> fb_rect{};
if (color_surface != nullptr && depth_surface != nullptr) { if (color_surface != nullptr && depth_surface != nullptr) {
fb_rect = color_rect; fb_rect = color_rect;
// Color and Depth surfaces must have the same dimensions and offsets // Color and Depth surfaces must have the same dimensions and offsets
@ -1560,7 +1560,7 @@ Surface RasterizerCacheOpenGL::GetFillSurface(const GPU::Regs::MemoryFillConfig&
} }
SurfaceRect_Tuple RasterizerCacheOpenGL::GetTexCopySurface(const SurfaceParams& params) { SurfaceRect_Tuple RasterizerCacheOpenGL::GetTexCopySurface(const SurfaceParams& params) {
MathUtil::Rectangle<u32> rect{}; Common::Rectangle<u32> rect{};
Surface match_surface = FindMatch<MatchFlags::TexCopy | MatchFlags::Invalid>( Surface match_surface = FindMatch<MatchFlags::TexCopy | MatchFlags::Invalid>(
surface_cache, params, ScaleMatch::Ignore); surface_cache, params, ScaleMatch::Ignore);

View File

@ -88,8 +88,8 @@ static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval
std::is_same<SurfaceMap::interval_type, SurfaceCache::interval_type>(), std::is_same<SurfaceMap::interval_type, SurfaceCache::interval_type>(),
"incorrect interval types"); "incorrect interval types");
using SurfaceRect_Tuple = std::tuple<Surface, MathUtil::Rectangle<u32>>; using SurfaceRect_Tuple = std::tuple<Surface, Common::Rectangle<u32>>;
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, MathUtil::Rectangle<u32>>; using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, Common::Rectangle<u32>>;
using PageMap = boost::icl::interval_map<u32, int>; using PageMap = boost::icl::interval_map<u32, int>;
@ -250,7 +250,7 @@ struct SurfaceParams {
// Returns the outer rectangle containing "interval" // Returns the outer rectangle containing "interval"
SurfaceParams FromInterval(SurfaceInterval interval) const; SurfaceParams FromInterval(SurfaceInterval interval) const;
SurfaceInterval GetSubRectInterval(MathUtil::Rectangle<u32> unscaled_rect) const; SurfaceInterval GetSubRectInterval(Common::Rectangle<u32> unscaled_rect) const;
// Returns the region of the biggest valid rectange within interval // Returns the region of the biggest valid rectange within interval
SurfaceInterval GetCopyableInterval(const Surface& src_surface) const; SurfaceInterval GetCopyableInterval(const Surface& src_surface) const;
@ -263,11 +263,11 @@ struct SurfaceParams {
return height * res_scale; return height * res_scale;
} }
MathUtil::Rectangle<u32> GetRect() const { Common::Rectangle<u32> GetRect() const {
return {0, height, width, 0}; return {0, height, width, 0};
} }
MathUtil::Rectangle<u32> GetScaledRect() const { Common::Rectangle<u32> GetScaledRect() const {
return {0, GetScaledHeight(), GetScaledWidth(), 0}; return {0, GetScaledHeight(), GetScaledWidth(), 0};
} }
@ -284,8 +284,8 @@ struct SurfaceParams {
bool CanExpand(const SurfaceParams& expanded_surface) const; bool CanExpand(const SurfaceParams& expanded_surface) const;
bool CanTexCopy(const SurfaceParams& texcopy_params) const; bool CanTexCopy(const SurfaceParams& texcopy_params) const;
MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const; Common::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const;
MathUtil::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const; Common::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const;
PAddr addr = 0; PAddr addr = 0;
PAddr end = 0; PAddr end = 0;
@ -373,9 +373,9 @@ struct CachedSurface : SurfaceParams, std::enable_shared_from_this<CachedSurface
void FlushGLBuffer(PAddr flush_start, PAddr flush_end); void FlushGLBuffer(PAddr flush_start, PAddr flush_end);
// Upload/Download data in gl_buffer in/to this surface's texture // Upload/Download data in gl_buffer in/to this surface's texture
void UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, void UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint read_fb_handle,
GLuint draw_fb_handle); GLuint draw_fb_handle);
void DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, void DownloadGLTexture(const Common::Rectangle<u32>& rect, GLuint read_fb_handle,
GLuint draw_fb_handle); GLuint draw_fb_handle);
std::shared_ptr<SurfaceWatcher> CreateWatcher() { std::shared_ptr<SurfaceWatcher> CreateWatcher() {
@ -413,11 +413,11 @@ public:
~RasterizerCacheOpenGL(); ~RasterizerCacheOpenGL();
/// Blit one surface's texture to another /// Blit one surface's texture to another
bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle<u32>& src_rect, bool BlitSurfaces(const Surface& src_surface, const Common::Rectangle<u32>& src_rect,
const Surface& dst_surface, const MathUtil::Rectangle<u32>& dst_rect); const Surface& dst_surface, const Common::Rectangle<u32>& dst_rect);
void ConvertD24S8toABGR(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, void ConvertD24S8toABGR(GLuint src_tex, const Common::Rectangle<u32>& src_rect, GLuint dst_tex,
GLuint dst_tex, const MathUtil::Rectangle<u32>& dst_rect); const Common::Rectangle<u32>& dst_rect);
/// Copy one surface's region to another /// Copy one surface's region to another
void CopySurface(const Surface& src_surface, const Surface& dst_surface, void CopySurface(const Surface& src_surface, const Surface& dst_surface,
@ -441,7 +441,7 @@ public:
/// Get the color and depth surfaces based on the framebuffer configuration /// Get the color and depth surfaces based on the framebuffer configuration
SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
const MathUtil::Rectangle<s32>& viewport_rect); const Common::Rectangle<s32>& viewport_rect);
/// Get a surface that matches the fill config /// Get a surface that matches the fill config
Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config); Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config);

View File

@ -221,7 +221,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram
static_cast<u32>(pixel_stride), screen_info)) { static_cast<u32>(pixel_stride), screen_info)) {
// Reset the screen info's display texture to its own permanent texture // Reset the screen info's display texture to its own permanent texture
screen_info.display_texture = screen_info.texture.resource.handle; screen_info.display_texture = screen_info.texture.resource.handle;
screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); screen_info.display_texcoords = Common::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height);

View File

@ -32,7 +32,7 @@ struct TextureInfo {
/// Structure used for storing information about the display target for each 3DS screen /// Structure used for storing information about the display target for each 3DS screen
struct ScreenInfo { struct ScreenInfo {
GLuint display_texture; GLuint display_texture;
MathUtil::Rectangle<float> display_texcoords; Common::Rectangle<float> display_texcoords;
TextureInfo texture; TextureInfo texture;
}; };

View File

@ -54,18 +54,18 @@ struct DebugData<true> {
LOOP_INT_IN = 0x800, LOOP_INT_IN = 0x800,
}; };
Math::Vec4<float24> src1; Common::Vec4<float24> src1;
Math::Vec4<float24> src2; Common::Vec4<float24> src2;
Math::Vec4<float24> src3; Common::Vec4<float24> src3;
Math::Vec4<float24> dest_in; Common::Vec4<float24> dest_in;
Math::Vec4<float24> dest_out; Common::Vec4<float24> dest_out;
s32 address_registers[2]; s32 address_registers[2];
bool conditional_code[2]; bool conditional_code[2];
bool cond_bool; bool cond_bool;
bool cond_cmp[2]; bool cond_cmp[2];
Math::Vec4<u8> loop_int; Common::Vec4<u8> loop_int;
u32 instruction_offset; u32 instruction_offset;
u32 next_instruction; u32 next_instruction;
@ -152,7 +152,8 @@ inline void SetField<DebugDataRecord::COND_CMP_IN>(DebugDataRecord& record, bool
} }
template <> template <>
inline void SetField<DebugDataRecord::LOOP_INT_IN>(DebugDataRecord& record, Math::Vec4<u8> value) { inline void SetField<DebugDataRecord::LOOP_INT_IN>(DebugDataRecord& record,
Common::Vec4<u8> value) {
record.loop_int = value; record.loop_int = value;
} }

View File

@ -85,7 +85,7 @@ void UnitState::LoadInput(const ShaderRegs& config, const AttributeBuffer& input
} }
} }
static void CopyRegistersToOutput(const Math::Vec4<float24>* regs, u32 mask, static void CopyRegistersToOutput(const Common::Vec4<float24>* regs, u32 mask,
AttributeBuffer& buffer) { AttributeBuffer& buffer) {
int output_i = 0; int output_i = 0;
for (int reg : Common::BitSet<u32>(mask)) { for (int reg : Common::BitSet<u32>(mask)) {
@ -107,7 +107,7 @@ GSEmitter::~GSEmitter() {
delete handlers; delete handlers;
} }
void GSEmitter::Emit(Math::Vec4<float24> (&output_regs)[16]) { void GSEmitter::Emit(Common::Vec4<float24> (&output_regs)[16]) {
ASSERT(vertex_id < 3); ASSERT(vertex_id < 3);
// TODO: This should be merged with UnitState::WriteOutput somehow // TODO: This should be merged with UnitState::WriteOutput somehow
CopyRegistersToOutput(output_regs, output_mask, buffer[vertex_id]); CopyRegistersToOutput(output_regs, output_mask, buffer[vertex_id]);

View File

@ -28,7 +28,7 @@ constexpr unsigned MAX_PROGRAM_CODE_LENGTH = 4096;
constexpr unsigned MAX_SWIZZLE_DATA_LENGTH = 4096; constexpr unsigned MAX_SWIZZLE_DATA_LENGTH = 4096;
struct AttributeBuffer { struct AttributeBuffer {
alignas(16) Math::Vec4<float24> attr[16]; alignas(16) Common::Vec4<float24> attr[16];
}; };
/// Handler type for receiving vertex outputs from vertex shader or geometry shader /// Handler type for receiving vertex outputs from vertex shader or geometry shader
@ -38,16 +38,16 @@ using VertexHandler = std::function<void(const AttributeBuffer&)>;
using WindingSetter = std::function<void()>; using WindingSetter = std::function<void()>;
struct OutputVertex { struct OutputVertex {
Math::Vec4<float24> pos; Common::Vec4<float24> pos;
Math::Vec4<float24> quat; Common::Vec4<float24> quat;
Math::Vec4<float24> color; Common::Vec4<float24> color;
Math::Vec2<float24> tc0; Common::Vec2<float24> tc0;
Math::Vec2<float24> tc1; Common::Vec2<float24> tc1;
float24 tc0_w; float24 tc0_w;
INSERT_PADDING_WORDS(1); INSERT_PADDING_WORDS(1);
Math::Vec3<float24> view; Common::Vec3<float24> view;
INSERT_PADDING_WORDS(1); INSERT_PADDING_WORDS(1);
Math::Vec2<float24> tc2; Common::Vec2<float24> tc2;
static void ValidateSemantics(const RasterizerRegs& regs); static void ValidateSemantics(const RasterizerRegs& regs);
static OutputVertex FromAttributeBuffer(const RasterizerRegs& regs, static OutputVertex FromAttributeBuffer(const RasterizerRegs& regs,
@ -87,7 +87,7 @@ struct GSEmitter {
GSEmitter(); GSEmitter();
~GSEmitter(); ~GSEmitter();
void Emit(Math::Vec4<float24> (&output_regs)[16]); void Emit(Common::Vec4<float24> (&output_regs)[16]);
}; };
static_assert(std::is_standard_layout<GSEmitter>::value, "GSEmitter is not standard layout type"); static_assert(std::is_standard_layout<GSEmitter>::value, "GSEmitter is not standard layout type");
@ -102,9 +102,9 @@ struct UnitState {
struct Registers { struct Registers {
// The registers are accessed by the shader JIT using SSE instructions, and are therefore // The registers are accessed by the shader JIT using SSE instructions, and are therefore
// required to be 16-byte aligned. // required to be 16-byte aligned.
alignas(16) Math::Vec4<float24> input[16]; alignas(16) Common::Vec4<float24> input[16];
alignas(16) Math::Vec4<float24> temporary[16]; alignas(16) Common::Vec4<float24> temporary[16];
alignas(16) Math::Vec4<float24> output[16]; alignas(16) Common::Vec4<float24> output[16];
} registers; } registers;
static_assert(std::is_pod<Registers>::value, "Structure is not POD"); static_assert(std::is_pod<Registers>::value, "Structure is not POD");
@ -120,11 +120,11 @@ struct UnitState {
switch (reg.GetRegisterType()) { switch (reg.GetRegisterType()) {
case RegisterType::Input: case RegisterType::Input:
return offsetof(UnitState, registers.input) + return offsetof(UnitState, registers.input) +
reg.GetIndex() * sizeof(Math::Vec4<float24>); reg.GetIndex() * sizeof(Common::Vec4<float24>);
case RegisterType::Temporary: case RegisterType::Temporary:
return offsetof(UnitState, registers.temporary) + return offsetof(UnitState, registers.temporary) +
reg.GetIndex() * sizeof(Math::Vec4<float24>); reg.GetIndex() * sizeof(Common::Vec4<float24>);
default: default:
UNREACHABLE(); UNREACHABLE();
@ -136,11 +136,11 @@ struct UnitState {
switch (reg.GetRegisterType()) { switch (reg.GetRegisterType()) {
case RegisterType::Output: case RegisterType::Output:
return offsetof(UnitState, registers.output) + return offsetof(UnitState, registers.output) +
reg.GetIndex() * sizeof(Math::Vec4<float24>); reg.GetIndex() * sizeof(Common::Vec4<float24>);
case RegisterType::Temporary: case RegisterType::Temporary:
return offsetof(UnitState, registers.temporary) + return offsetof(UnitState, registers.temporary) +
reg.GetIndex() * sizeof(Math::Vec4<float24>); reg.GetIndex() * sizeof(Common::Vec4<float24>);
default: default:
UNREACHABLE(); UNREACHABLE();
@ -175,13 +175,13 @@ struct GSUnitState : public UnitState {
struct Uniforms { struct Uniforms {
// The float uniforms are accessed by the shader JIT using SSE instructions, and are // The float uniforms are accessed by the shader JIT using SSE instructions, and are
// therefore required to be 16-byte aligned. // therefore required to be 16-byte aligned.
alignas(16) Math::Vec4<float24> f[96]; alignas(16) Common::Vec4<float24> f[96];
std::array<bool, 16> b; std::array<bool, 16> b;
std::array<Math::Vec4<u8>, 4> i; std::array<Common::Vec4<u8>, 4> i;
static std::size_t GetFloatUniformOffset(unsigned index) { static std::size_t GetFloatUniformOffset(unsigned index) {
return offsetof(Uniforms, f) + index * sizeof(Math::Vec4<float24>); return offsetof(Uniforms, f) + index * sizeof(Common::Vec4<float24>);
} }
static std::size_t GetBoolUniformOffset(unsigned index) { static std::size_t GetBoolUniformOffset(unsigned index) {
@ -189,7 +189,7 @@ struct Uniforms {
} }
static std::size_t GetIntUniformOffset(unsigned index) { static std::size_t GetIntUniformOffset(unsigned index) {
return offsetof(Uniforms, i) + index * sizeof(Math::Vec4<u8>); return offsetof(Uniforms, i) + index * sizeof(Common::Vec4<u8>);
} }
}; };

View File

@ -622,10 +622,10 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData
} }
case OpCode::Id::LOOP: { case OpCode::Id::LOOP: {
Math::Vec4<u8> loop_param(uniforms.i[instr.flow_control.int_uniform_id].x, Common::Vec4<u8> loop_param(uniforms.i[instr.flow_control.int_uniform_id].x,
uniforms.i[instr.flow_control.int_uniform_id].y, uniforms.i[instr.flow_control.int_uniform_id].y,
uniforms.i[instr.flow_control.int_uniform_id].z, uniforms.i[instr.flow_control.int_uniform_id].z,
uniforms.i[instr.flow_control.int_uniform_id].w); uniforms.i[instr.flow_control.int_uniform_id].w);
state.address_registers[2] = loop_param.y; state.address_registers[2] = loop_param.y;
Record<DebugDataRecord::LOOP_INT_IN>(debug_data, iteration, loop_param); Record<DebugDataRecord::LOOP_INT_IN>(debug_data, iteration, loop_param);
@ -688,7 +688,7 @@ DebugData<true> InterpreterEngine::ProduceDebugInfo(const ShaderSetup& setup,
DebugData<true> debug_data; DebugData<true> debug_data;
// Setup input register table // Setup input register table
boost::fill(state.registers.input, Math::Vec4<float24>::AssignToAll(float24::Zero())); boost::fill(state.registers.input, Common::Vec4<float24>::AssignToAll(float24::Zero()));
state.LoadInput(config, input); state.LoadInput(config, input);
RunInterpreter(setup, state, debug_data, setup.engine_data.entry_point); RunInterpreter(setup, state, debug_data, setup.engine_data.entry_point);
return debug_data; return debug_data;

View File

@ -777,7 +777,7 @@ void JitShader::Compile_JMP(Instruction instr) {
} }
} }
static void Emit(GSEmitter* emitter, Math::Vec4<float24> (*output)[16]) { static void Emit(GSEmitter* emitter, Common::Vec4<float24> (*output)[16]) {
emitter->Emit(*output); emitter->Emit(*output);
} }

View File

@ -23,13 +23,15 @@ namespace Pica::Clipper {
struct ClippingEdge { struct ClippingEdge {
public: public:
ClippingEdge(Math::Vec4<float24> coeffs, Math::Vec4<float24> bias = Math::Vec4<float24>( ClippingEdge(Common::Vec4<float24> coeffs,
float24::FromFloat32(0), float24::FromFloat32(0), Common::Vec4<float24> bias = Common::Vec4<float24>(float24::FromFloat32(0),
float24::FromFloat32(0), float24::FromFloat32(0))) float24::FromFloat32(0),
float24::FromFloat32(0),
float24::FromFloat32(0)))
: coeffs(coeffs), bias(bias) {} : coeffs(coeffs), bias(bias) {}
bool IsInside(const Vertex& vertex) const { bool IsInside(const Vertex& vertex) const {
return Math::Dot(vertex.pos + bias, coeffs) >= float24::FromFloat32(0); return Common::Dot(vertex.pos + bias, coeffs) >= float24::FromFloat32(0);
} }
bool IsOutSide(const Vertex& vertex) const { bool IsOutSide(const Vertex& vertex) const {
@ -37,8 +39,8 @@ public:
} }
Vertex GetIntersection(const Vertex& v0, const Vertex& v1) const { Vertex GetIntersection(const Vertex& v0, const Vertex& v1) const {
float24 dp = Math::Dot(v0.pos + bias, coeffs); float24 dp = Common::Dot(v0.pos + bias, coeffs);
float24 dp_prev = Math::Dot(v1.pos + bias, coeffs); float24 dp_prev = Common::Dot(v1.pos + bias, coeffs);
float24 factor = dp_prev / (dp_prev - dp); float24 factor = dp_prev / (dp_prev - dp);
return Vertex::Lerp(factor, v0, v1); return Vertex::Lerp(factor, v0, v1);
@ -46,8 +48,8 @@ public:
private: private:
float24 pos; float24 pos;
Math::Vec4<float24> coeffs; Common::Vec4<float24> coeffs;
Math::Vec4<float24> bias; Common::Vec4<float24> bias;
}; };
static void InitScreenCoordinates(Vertex& vtx) { static void InitScreenCoordinates(Vertex& vtx) {
@ -95,7 +97,7 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu
static_vector<Vertex, MAX_VERTICES> buffer_b; static_vector<Vertex, MAX_VERTICES> buffer_b;
auto FlipQuaternionIfOpposite = [](auto& a, const auto& b) { auto FlipQuaternionIfOpposite = [](auto& a, const auto& b) {
if (Math::Dot(a, b) < float24::Zero()) if (Common::Dot(a, b) < float24::Zero())
a = a * float24::FromFloat32(-1.0f); a = a * float24::FromFloat32(-1.0f);
}; };
@ -114,13 +116,14 @@ void ProcessTriangle(const OutputVertex& v0, const OutputVertex& v1, const Outpu
static const float24 f0 = float24::FromFloat32(0.0); static const float24 f0 = float24::FromFloat32(0.0);
static const float24 f1 = float24::FromFloat32(1.0); static const float24 f1 = float24::FromFloat32(1.0);
static const std::array<ClippingEdge, 7> clipping_edges = {{ static const std::array<ClippingEdge, 7> clipping_edges = {{
{Math::MakeVec(-f1, f0, f0, f1)}, // x = +w {Common::MakeVec(-f1, f0, f0, f1)}, // x = +w
{Math::MakeVec(f1, f0, f0, f1)}, // x = -w {Common::MakeVec(f1, f0, f0, f1)}, // x = -w
{Math::MakeVec(f0, -f1, f0, f1)}, // y = +w {Common::MakeVec(f0, -f1, f0, f1)}, // y = +w
{Math::MakeVec(f0, f1, f0, f1)}, // y = -w {Common::MakeVec(f0, f1, f0, f1)}, // y = -w
{Math::MakeVec(f0, f0, -f1, f0)}, // z = 0 {Common::MakeVec(f0, f0, -f1, f0)}, // z = 0
{Math::MakeVec(f0, f0, f1, f1)}, // z = -w {Common::MakeVec(f0, f0, f1, f1)}, // z = -w
{Math::MakeVec(f0, f0, f0, f1), Math::Vec4<float24>(f0, f0, f0, EPSILON)}, // w = EPSILON {Common::MakeVec(f0, f0, f0, f1),
Common::Vec4<float24>(f0, f0, f0, EPSILON)}, // w = EPSILON
}}; }};
// Simple implementation of the Sutherland-Hodgman clipping algorithm. // Simple implementation of the Sutherland-Hodgman clipping algorithm.

View File

@ -18,7 +18,7 @@
namespace Pica::Rasterizer { namespace Pica::Rasterizer {
void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { void DrawPixel(int x, int y, const Common::Vec4<u8>& color) {
const auto& framebuffer = g_state.regs.framebuffer.framebuffer; const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); const PAddr addr = framebuffer.GetColorBufferPhysicalAddress();
@ -61,7 +61,7 @@ void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
} }
} }
const Math::Vec4<u8> GetPixel(int x, int y) { const Common::Vec4<u8> GetPixel(int x, int y) {
const auto& framebuffer = g_state.regs.framebuffer.framebuffer; const auto& framebuffer = g_state.regs.framebuffer.framebuffer;
const PAddr addr = framebuffer.GetColorBufferPhysicalAddress(); const PAddr addr = framebuffer.GetColorBufferPhysicalAddress();
@ -257,10 +257,12 @@ u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u
} }
} }
Math::Vec4<u8> EvaluateBlendEquation(const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, Common::Vec4<u8> EvaluateBlendEquation(const Common::Vec4<u8>& src,
const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor, const Common::Vec4<u8>& srcfactor,
FramebufferRegs::BlendEquation equation) { const Common::Vec4<u8>& dest,
Math::Vec4<int> result; const Common::Vec4<u8>& destfactor,
FramebufferRegs::BlendEquation equation) {
Common::Vec4<int> result;
auto src_result = (src * srcfactor).Cast<int>(); auto src_result = (src * srcfactor).Cast<int>();
auto dst_result = (dest * destfactor).Cast<int>(); auto dst_result = (dest * destfactor).Cast<int>();
@ -299,8 +301,8 @@ Math::Vec4<u8> EvaluateBlendEquation(const Math::Vec4<u8>& src, const Math::Vec4
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
return Math::Vec4<u8>(std::clamp(result.r(), 0, 255), std::clamp(result.g(), 0, 255), return Common::Vec4<u8>(std::clamp(result.r(), 0, 255), std::clamp(result.g(), 0, 255),
std::clamp(result.b(), 0, 255), std::clamp(result.a(), 0, 255)); std::clamp(result.b(), 0, 255), std::clamp(result.a(), 0, 255));
}; };
u8 LogicOp(u8 src, u8 dest, FramebufferRegs::LogicOp op) { u8 LogicOp(u8 src, u8 dest, FramebufferRegs::LogicOp op) {
@ -359,7 +361,7 @@ u8 LogicOp(u8 src, u8 dest, FramebufferRegs::LogicOp op) {
// Decode/Encode for shadow map format. It is similar to D24S8 format, but the depth field is in // Decode/Encode for shadow map format. It is similar to D24S8 format, but the depth field is in
// big-endian // big-endian
static const Math::Vec2<u32> DecodeD24S8Shadow(const u8* bytes) { static const Common::Vec2<u32> DecodeD24S8Shadow(const u8* bytes) {
return {static_cast<u32>((bytes[0] << 16) | (bytes[1] << 8) | bytes[2]), bytes[3]}; return {static_cast<u32>((bytes[0] << 16) | (bytes[1] << 8) | bytes[2]), bytes[3]};
} }

View File

@ -10,17 +10,19 @@
namespace Pica::Rasterizer { namespace Pica::Rasterizer {
void DrawPixel(int x, int y, const Math::Vec4<u8>& color); void DrawPixel(int x, int y, const Common::Vec4<u8>& color);
const Math::Vec4<u8> GetPixel(int x, int y); const Common::Vec4<u8> GetPixel(int x, int y);
u32 GetDepth(int x, int y); u32 GetDepth(int x, int y);
u8 GetStencil(int x, int y); u8 GetStencil(int x, int y);
void SetDepth(int x, int y, u32 value); void SetDepth(int x, int y, u32 value);
void SetStencil(int x, int y, u8 value); void SetStencil(int x, int y, u8 value);
u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref); u8 PerformStencilAction(FramebufferRegs::StencilAction action, u8 old_stencil, u8 ref);
Math::Vec4<u8> EvaluateBlendEquation(const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, Common::Vec4<u8> EvaluateBlendEquation(const Common::Vec4<u8>& src,
const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor, const Common::Vec4<u8>& srcfactor,
FramebufferRegs::BlendEquation equation); const Common::Vec4<u8>& dest,
const Common::Vec4<u8>& destfactor,
FramebufferRegs::BlendEquation equation);
u8 LogicOp(u8 src, u8 dest, FramebufferRegs::LogicOp op); u8 LogicOp(u8 src, u8 dest, FramebufferRegs::LogicOp op);

View File

@ -20,63 +20,63 @@ static float LookupLightingLut(const Pica::State::Lighting& lighting, std::size_
return lut_value + lut_diff * delta; return lut_value + lut_diff * delta;
} }
std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors( std::tuple<Common::Vec4<u8>, Common::Vec4<u8>> ComputeFragmentsColors(
const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state,
const Math::Quaternion<float>& normquat, const Math::Vec3<float>& view, const Common::Quaternion<float>& normquat, const Common::Vec3<float>& view,
const Math::Vec4<u8> (&texture_color)[4]) { const Common::Vec4<u8> (&texture_color)[4]) {
Math::Vec4<float> shadow; Common::Vec4<float> shadow;
if (lighting.config0.enable_shadow) { if (lighting.config0.enable_shadow) {
shadow = texture_color[lighting.config0.shadow_selector].Cast<float>() / 255.0f; shadow = texture_color[lighting.config0.shadow_selector].Cast<float>() / 255.0f;
if (lighting.config0.shadow_invert) { if (lighting.config0.shadow_invert) {
shadow = Math::MakeVec(1.0f, 1.0f, 1.0f, 1.0f) - shadow; shadow = Common::MakeVec(1.0f, 1.0f, 1.0f, 1.0f) - shadow;
} }
} else { } else {
shadow = Math::MakeVec(1.0f, 1.0f, 1.0f, 1.0f); shadow = Common::MakeVec(1.0f, 1.0f, 1.0f, 1.0f);
} }
Math::Vec3<float> surface_normal; Common::Vec3<float> surface_normal;
Math::Vec3<float> surface_tangent; Common::Vec3<float> surface_tangent;
if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) { if (lighting.config0.bump_mode != LightingRegs::LightingBumpMode::None) {
Math::Vec3<float> perturbation = Common::Vec3<float> perturbation =
texture_color[lighting.config0.bump_selector].xyz().Cast<float>() / 127.5f - texture_color[lighting.config0.bump_selector].xyz().Cast<float>() / 127.5f -
Math::MakeVec(1.0f, 1.0f, 1.0f); Common::MakeVec(1.0f, 1.0f, 1.0f);
if (lighting.config0.bump_mode == LightingRegs::LightingBumpMode::NormalMap) { if (lighting.config0.bump_mode == LightingRegs::LightingBumpMode::NormalMap) {
if (!lighting.config0.disable_bump_renorm) { if (!lighting.config0.disable_bump_renorm) {
const float z_square = 1 - perturbation.xy().Length2(); const float z_square = 1 - perturbation.xy().Length2();
perturbation.z = std::sqrt(std::max(z_square, 0.0f)); perturbation.z = std::sqrt(std::max(z_square, 0.0f));
} }
surface_normal = perturbation; surface_normal = perturbation;
surface_tangent = Math::MakeVec(1.0f, 0.0f, 0.0f); surface_tangent = Common::MakeVec(1.0f, 0.0f, 0.0f);
} else if (lighting.config0.bump_mode == LightingRegs::LightingBumpMode::TangentMap) { } else if (lighting.config0.bump_mode == LightingRegs::LightingBumpMode::TangentMap) {
surface_normal = Math::MakeVec(0.0f, 0.0f, 1.0f); surface_normal = Common::MakeVec(0.0f, 0.0f, 1.0f);
surface_tangent = perturbation; surface_tangent = perturbation;
} else { } else {
LOG_ERROR(HW_GPU, "Unknown bump mode {}", LOG_ERROR(HW_GPU, "Unknown bump mode {}",
static_cast<u32>(lighting.config0.bump_mode.Value())); static_cast<u32>(lighting.config0.bump_mode.Value()));
} }
} else { } else {
surface_normal = Math::MakeVec(0.0f, 0.0f, 1.0f); surface_normal = Common::MakeVec(0.0f, 0.0f, 1.0f);
surface_tangent = Math::MakeVec(1.0f, 0.0f, 0.0f); surface_tangent = Common::MakeVec(1.0f, 0.0f, 0.0f);
} }
// Use the normalized the quaternion when performing the rotation // Use the normalized the quaternion when performing the rotation
auto normal = Math::QuaternionRotate(normquat, surface_normal); auto normal = Common::QuaternionRotate(normquat, surface_normal);
auto tangent = Math::QuaternionRotate(normquat, surface_tangent); auto tangent = Common::QuaternionRotate(normquat, surface_tangent);
Math::Vec4<float> diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f}; Common::Vec4<float> diffuse_sum = {0.0f, 0.0f, 0.0f, 1.0f};
Math::Vec4<float> specular_sum = {0.0f, 0.0f, 0.0f, 1.0f}; Common::Vec4<float> specular_sum = {0.0f, 0.0f, 0.0f, 1.0f};
for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) { for (unsigned light_index = 0; light_index <= lighting.max_light_index; ++light_index) {
unsigned num = lighting.light_enable.GetNum(light_index); unsigned num = lighting.light_enable.GetNum(light_index);
const auto& light_config = lighting.light[num]; const auto& light_config = lighting.light[num];
Math::Vec3<float> refl_value = {}; Common::Vec3<float> refl_value = {};
Math::Vec3<float> position = {float16::FromRaw(light_config.x).ToFloat32(), Common::Vec3<float> position = {float16::FromRaw(light_config.x).ToFloat32(),
float16::FromRaw(light_config.y).ToFloat32(), float16::FromRaw(light_config.y).ToFloat32(),
float16::FromRaw(light_config.z).ToFloat32()}; float16::FromRaw(light_config.z).ToFloat32()};
Math::Vec3<float> light_vector; Common::Vec3<float> light_vector;
if (light_config.config.directional) if (light_config.config.directional)
light_vector = position; light_vector = position;
@ -85,8 +85,8 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
light_vector.Normalize(); light_vector.Normalize();
Math::Vec3<float> norm_view = view.Normalized(); Common::Vec3<float> norm_view = view.Normalized();
Math::Vec3<float> half_vector = norm_view + light_vector; Common::Vec3<float> half_vector = norm_view + light_vector;
float dist_atten = 1.0f; float dist_atten = 1.0f;
if (!lighting.IsDistAttenDisabled(num)) { if (!lighting.IsDistAttenDisabled(num)) {
@ -111,33 +111,33 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
switch (input) { switch (input) {
case LightingRegs::LightingLutInput::NH: case LightingRegs::LightingLutInput::NH:
result = Math::Dot(normal, half_vector.Normalized()); result = Common::Dot(normal, half_vector.Normalized());
break; break;
case LightingRegs::LightingLutInput::VH: case LightingRegs::LightingLutInput::VH:
result = Math::Dot(norm_view, half_vector.Normalized()); result = Common::Dot(norm_view, half_vector.Normalized());
break; break;
case LightingRegs::LightingLutInput::NV: case LightingRegs::LightingLutInput::NV:
result = Math::Dot(normal, norm_view); result = Common::Dot(normal, norm_view);
break; break;
case LightingRegs::LightingLutInput::LN: case LightingRegs::LightingLutInput::LN:
result = Math::Dot(light_vector, normal); result = Common::Dot(light_vector, normal);
break; break;
case LightingRegs::LightingLutInput::SP: { case LightingRegs::LightingLutInput::SP: {
Math::Vec3<s32> spot_dir{light_config.spot_x.Value(), light_config.spot_y.Value(), Common::Vec3<s32> spot_dir{light_config.spot_x.Value(), light_config.spot_y.Value(),
light_config.spot_z.Value()}; light_config.spot_z.Value()};
result = Math::Dot(light_vector, spot_dir.Cast<float>() / 2047.0f); result = Common::Dot(light_vector, spot_dir.Cast<float>() / 2047.0f);
break; break;
} }
case LightingRegs::LightingLutInput::CP: case LightingRegs::LightingLutInput::CP:
if (lighting.config0.config == LightingRegs::LightingConfig::Config7) { if (lighting.config0.config == LightingRegs::LightingConfig::Config7) {
const Math::Vec3<float> norm_half_vector = half_vector.Normalized(); const Common::Vec3<float> norm_half_vector = half_vector.Normalized();
const Math::Vec3<float> half_vector_proj = const Common::Vec3<float> half_vector_proj =
norm_half_vector - normal * Math::Dot(normal, norm_half_vector); norm_half_vector - normal * Common::Dot(normal, norm_half_vector);
result = Math::Dot(half_vector_proj, tangent); result = Common::Dot(half_vector_proj, tangent);
} else { } else {
result = 0.0f; result = 0.0f;
} }
@ -192,7 +192,7 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
lighting.lut_scale.d0, LightingRegs::LightingSampler::Distribution0); lighting.lut_scale.d0, LightingRegs::LightingSampler::Distribution0);
} }
Math::Vec3<float> specular_0 = d0_lut_value * light_config.specular_0.ToVec3f(); Common::Vec3<float> specular_0 = d0_lut_value * light_config.specular_0.ToVec3f();
// If enabled, lookup ReflectRed value, otherwise, 1.0 is used // If enabled, lookup ReflectRed value, otherwise, 1.0 is used
if (lighting.config1.disable_lut_rr == 0 && if (lighting.config1.disable_lut_rr == 0 &&
@ -237,7 +237,7 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
lighting.lut_scale.d1, LightingRegs::LightingSampler::Distribution1); lighting.lut_scale.d1, LightingRegs::LightingSampler::Distribution1);
} }
Math::Vec3<float> specular_1 = Common::Vec3<float> specular_1 =
d1_lut_value * refl_value * light_config.specular_1.ToVec3f(); d1_lut_value * refl_value * light_config.specular_1.ToVec3f();
// Fresnel // Fresnel
@ -261,7 +261,7 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
} }
} }
auto dot_product = Math::Dot(light_vector, normal); auto dot_product = Common::Dot(light_vector, normal);
if (light_config.config.two_sided_diffuse) if (light_config.config.two_sided_diffuse)
dot_product = std::abs(dot_product); dot_product = std::abs(dot_product);
else else
@ -297,8 +297,8 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
} }
} }
diffuse_sum += Math::MakeVec(diffuse, 0.0f); diffuse_sum += Common::MakeVec(diffuse, 0.0f);
specular_sum += Math::MakeVec(specular, 0.0f); specular_sum += Common::MakeVec(specular, 0.0f);
} }
if (lighting.config0.shadow_alpha) { if (lighting.config0.shadow_alpha) {
@ -314,17 +314,17 @@ std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors(
} }
} }
diffuse_sum += Math::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f); diffuse_sum += Common::MakeVec(lighting.global_ambient.ToVec3f(), 0.0f);
auto diffuse = Math::MakeVec<float>(std::clamp(diffuse_sum.x, 0.0f, 1.0f) * 255, auto diffuse = Common::MakeVec<float>(std::clamp(diffuse_sum.x, 0.0f, 1.0f) * 255,
std::clamp(diffuse_sum.y, 0.0f, 1.0f) * 255, std::clamp(diffuse_sum.y, 0.0f, 1.0f) * 255,
std::clamp(diffuse_sum.z, 0.0f, 1.0f) * 255, std::clamp(diffuse_sum.z, 0.0f, 1.0f) * 255,
std::clamp(diffuse_sum.w, 0.0f, 1.0f) * 255) std::clamp(diffuse_sum.w, 0.0f, 1.0f) * 255)
.Cast<u8>(); .Cast<u8>();
auto specular = Math::MakeVec<float>(std::clamp(specular_sum.x, 0.0f, 1.0f) * 255, auto specular = Common::MakeVec<float>(std::clamp(specular_sum.x, 0.0f, 1.0f) * 255,
std::clamp(specular_sum.y, 0.0f, 1.0f) * 255, std::clamp(specular_sum.y, 0.0f, 1.0f) * 255,
std::clamp(specular_sum.z, 0.0f, 1.0f) * 255, std::clamp(specular_sum.z, 0.0f, 1.0f) * 255,
std::clamp(specular_sum.w, 0.0f, 1.0f) * 255) std::clamp(specular_sum.w, 0.0f, 1.0f) * 255)
.Cast<u8>(); .Cast<u8>();
return std::make_tuple(diffuse, specular); return std::make_tuple(diffuse, specular);
} }

View File

@ -11,9 +11,9 @@
namespace Pica { namespace Pica {
std::tuple<Math::Vec4<u8>, Math::Vec4<u8>> ComputeFragmentsColors( std::tuple<Common::Vec4<u8>, Common::Vec4<u8>> ComputeFragmentsColors(
const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state, const Pica::LightingRegs& lighting, const Pica::State::Lighting& lighting_state,
const Math::Quaternion<float>& normquat, const Math::Vec3<float>& view, const Common::Quaternion<float>& normquat, const Common::Vec3<float>& view,
const Math::Vec4<u8> (&texture_color)[4]); const Common::Vec4<u8> (&texture_color)[4]);
} // namespace Pica } // namespace Pica

View File

@ -63,7 +63,7 @@ static float NoiseCoef(float u, float v, TexturingRegs regs, State::ProcTex stat
const float g3 = NoiseRand2D(x_int + 1, y_int + 1) * (x_frac + y_frac - 2); const float g3 = NoiseRand2D(x_int + 1, y_int + 1) * (x_frac + y_frac - 2);
const float x_noise = LookupLUT(state.noise_table, x_frac); const float x_noise = LookupLUT(state.noise_table, x_frac);
const float y_noise = LookupLUT(state.noise_table, y_frac); const float y_noise = LookupLUT(state.noise_table, y_frac);
return Math::BilinearInterp(g0, g1, g2, g3, x_noise, y_noise); return Common::BilinearInterp(g0, g1, g2, g3, x_noise, y_noise);
} }
static float GetShiftOffset(float v, ProcTexShift mode, ProcTexClamp clamp_mode) { static float GetShiftOffset(float v, ProcTexShift mode, ProcTexClamp clamp_mode) {
@ -154,7 +154,7 @@ float CombineAndMap(float u, float v, ProcTexCombiner combiner,
return LookupLUT(map_table, f); return LookupLUT(map_table, f);
} }
Math::Vec4<u8> ProcTex(float u, float v, TexturingRegs regs, State::ProcTex state) { Common::Vec4<u8> ProcTex(float u, float v, TexturingRegs regs, State::ProcTex state) {
u = std::abs(u); u = std::abs(u);
v = std::abs(v); v = std::abs(v);
@ -187,7 +187,7 @@ Math::Vec4<u8> ProcTex(float u, float v, TexturingRegs regs, State::ProcTex stat
const u32 offset = regs.proctex_lut_offset.level0; const u32 offset = regs.proctex_lut_offset.level0;
const u32 width = regs.proctex_lut.width; const u32 width = regs.proctex_lut.width;
const float index = offset + (lut_coord * (width - 1)); const float index = offset + (lut_coord * (width - 1));
Math::Vec4<u8> final_color; Common::Vec4<u8> final_color;
// TODO(wwylele): implement mipmap // TODO(wwylele): implement mipmap
switch (regs.proctex_lut.filter) { switch (regs.proctex_lut.filter) {
case ProcTexFilter::Linear: case ProcTexFilter::Linear:
@ -212,7 +212,7 @@ Math::Vec4<u8> ProcTex(float u, float v, TexturingRegs regs, State::ProcTex stat
// uses the output of CombineAndMap directly instead. // uses the output of CombineAndMap directly instead.
const float final_alpha = const float final_alpha =
CombineAndMap(u, v, regs.proctex.alpha_combiner, state.alpha_map_table); CombineAndMap(u, v, regs.proctex.alpha_combiner, state.alpha_map_table);
return Math::MakeVec<u8>(final_color.rgb(), static_cast<u8>(final_alpha * 255)); return Common::MakeVec<u8>(final_color.rgb(), static_cast<u8>(final_alpha * 255));
} else { } else {
return final_color; return final_color;
} }

View File

@ -9,6 +9,6 @@
namespace Pica::Rasterizer { namespace Pica::Rasterizer {
/// Generates procedural texture color for the given coordinates /// Generates procedural texture color for the given coordinates
Math::Vec4<u8> ProcTex(float u, float v, TexturingRegs regs, State::ProcTex state); Common::Vec4<u8> ProcTex(float u, float v, TexturingRegs regs, State::ProcTex state);
} // namespace Pica::Rasterizer } // namespace Pica::Rasterizer

View File

@ -64,12 +64,12 @@ private:
* *
* @todo define orientation concretely. * @todo define orientation concretely.
*/ */
static int SignedArea(const Math::Vec2<Fix12P4>& vtx1, const Math::Vec2<Fix12P4>& vtx2, static int SignedArea(const Common::Vec2<Fix12P4>& vtx1, const Common::Vec2<Fix12P4>& vtx2,
const Math::Vec2<Fix12P4>& vtx3) { const Common::Vec2<Fix12P4>& vtx3) {
const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0); const auto vec1 = Common::MakeVec(vtx2 - vtx1, 0);
const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0); const auto vec2 = Common::MakeVec(vtx3 - vtx1, 0);
// TODO: There is a very small chance this will overflow for sizeof(int) == 4 // TODO: There is a very small chance this will overflow for sizeof(int) == 4
return Math::Cross(vec1, vec2).z; return Common::Cross(vec1, vec2).z;
}; };
/// Convert a 3D vector for cube map coordinates to 2D texture coordinates along with the face name /// Convert a 3D vector for cube map coordinates to 2D texture coordinates along with the face name
@ -134,13 +134,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
// triangle borders. Is it that the correct solution, though? // triangle borders. Is it that the correct solution, though?
return Fix12P4(static_cast<unsigned short>(round(flt.ToFloat32() * 16.0f))); return Fix12P4(static_cast<unsigned short>(round(flt.ToFloat32() * 16.0f)));
}; };
static auto ScreenToRasterizerCoordinates = [](const Math::Vec3<float24>& vec) { static auto ScreenToRasterizerCoordinates = [](const Common::Vec3<float24>& vec) {
return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)}; return Common::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)};
}; };
Math::Vec3<Fix12P4> vtxpos[3]{ScreenToRasterizerCoordinates(v0.screenpos), Common::Vec3<Fix12P4> vtxpos[3]{ScreenToRasterizerCoordinates(v0.screenpos),
ScreenToRasterizerCoordinates(v1.screenpos), ScreenToRasterizerCoordinates(v1.screenpos),
ScreenToRasterizerCoordinates(v2.screenpos)}; ScreenToRasterizerCoordinates(v2.screenpos)};
if (regs.rasterizer.cull_mode == RasterizerRegs::CullMode::KeepAll) { if (regs.rasterizer.cull_mode == RasterizerRegs::CullMode::KeepAll) {
// Make sure we always end up with a triangle wound counter-clockwise // Make sure we always end up with a triangle wound counter-clockwise
@ -189,9 +189,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
// drawn. Pixels on any other triangle border are drawn. This is implemented with three bias // drawn. Pixels on any other triangle border are drawn. This is implemented with three bias
// values which are added to the barycentric coordinates w0, w1 and w2, respectively. // values which are added to the barycentric coordinates w0, w1 and w2, respectively.
// NOTE: These are the PSP filling rules. Not sure if the 3DS uses the same ones... // NOTE: These are the PSP filling rules. Not sure if the 3DS uses the same ones...
auto IsRightSideOrFlatBottomEdge = [](const Math::Vec2<Fix12P4>& vtx, auto IsRightSideOrFlatBottomEdge = [](const Common::Vec2<Fix12P4>& vtx,
const Math::Vec2<Fix12P4>& line1, const Common::Vec2<Fix12P4>& line1,
const Math::Vec2<Fix12P4>& line2) { const Common::Vec2<Fix12P4>& line2) {
if (line1.y == line2.y) { if (line1.y == line2.y) {
// just check if vertex is above us => bottom line parallel to x-axis // just check if vertex is above us => bottom line parallel to x-axis
return vtx.y < line1.y; return vtx.y < line1.y;
@ -210,7 +210,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
int bias2 = int bias2 =
IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0;
auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); auto w_inverse = Common::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
auto textures = regs.texturing.GetTextures(); auto textures = regs.texturing.GetTextures();
auto tev_stages = regs.texturing.GetTevStages(); auto tev_stages = regs.texturing.GetTevStages();
@ -243,11 +243,11 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
continue; continue;
auto baricentric_coordinates = auto baricentric_coordinates =
Math::MakeVec(float24::FromFloat32(static_cast<float>(w0)), Common::MakeVec(float24::FromFloat32(static_cast<float>(w0)),
float24::FromFloat32(static_cast<float>(w1)), float24::FromFloat32(static_cast<float>(w1)),
float24::FromFloat32(static_cast<float>(w2))); float24::FromFloat32(static_cast<float>(w2)));
float24 interpolated_w_inverse = float24 interpolated_w_inverse =
float24::FromFloat32(1.0f) / Math::Dot(w_inverse, baricentric_coordinates); float24::FromFloat32(1.0f) / Common::Dot(w_inverse, baricentric_coordinates);
// interpolated_z = z / w // interpolated_z = z / w
float interpolated_z_over_w = float interpolated_z_over_w =
@ -288,12 +288,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
// //
// The generalization to three vertices is straightforward in baricentric coordinates. // The generalization to three vertices is straightforward in baricentric coordinates.
auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) {
auto attr_over_w = Math::MakeVec(attr0, attr1, attr2); auto attr_over_w = Common::MakeVec(attr0, attr1, attr2);
float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); float24 interpolated_attr_over_w =
Common::Dot(attr_over_w, baricentric_coordinates);
return interpolated_attr_over_w * interpolated_w_inverse; return interpolated_attr_over_w * interpolated_w_inverse;
}; };
Math::Vec4<u8> primary_color{ Common::Vec4<u8> primary_color{
static_cast<u8>(round( static_cast<u8>(round(
GetInterpolatedAttribute(v0.color.r(), v1.color.r(), v2.color.r()).ToFloat32() * GetInterpolatedAttribute(v0.color.r(), v1.color.r(), v2.color.r()).ToFloat32() *
255)), 255)),
@ -308,7 +309,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
255)), 255)),
}; };
Math::Vec2<float24> uv[3]; Common::Vec2<float24> uv[3];
uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u());
uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v()); uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v());
uv[1].u() = GetInterpolatedAttribute(v0.tc1.u(), v1.tc1.u(), v2.tc1.u()); uv[1].u() = GetInterpolatedAttribute(v0.tc1.u(), v1.tc1.u(), v2.tc1.u());
@ -316,7 +317,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
uv[2].u() = GetInterpolatedAttribute(v0.tc2.u(), v1.tc2.u(), v2.tc2.u()); uv[2].u() = GetInterpolatedAttribute(v0.tc2.u(), v1.tc2.u(), v2.tc2.u());
uv[2].v() = GetInterpolatedAttribute(v0.tc2.v(), v1.tc2.v(), v2.tc2.v()); uv[2].v() = GetInterpolatedAttribute(v0.tc2.v(), v1.tc2.v(), v2.tc2.v());
Math::Vec4<u8> texture_color[4]{}; Common::Vec4<u8> texture_color[4]{};
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
const auto& texture = textures[i]; const auto& texture = textures[i];
if (!texture.enabled) if (!texture.enabled)
@ -391,9 +392,10 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
if (use_border_s || use_border_t) { if (use_border_s || use_border_t) {
auto border_color = texture.config.border_color; auto border_color = texture.config.border_color;
texture_color[i] = Math::MakeVec(border_color.r.Value(), border_color.g.Value(), texture_color[i] =
border_color.b.Value(), border_color.a.Value()) Common::MakeVec(border_color.r.Value(), border_color.g.Value(),
.Cast<u8>(); border_color.b.Value(), border_color.a.Value())
.Cast<u8>();
} else { } else {
// Textures are laid out from bottom to top, hence we invert the t coordinate. // Textures are laid out from bottom to top, hence we invert the t coordinate.
// NOTE: This may not be the right place for the inversion. // NOTE: This may not be the right place for the inversion.
@ -442,21 +444,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
// operations on each of them (e.g. inversion) and then calculate the output color // operations on each of them (e.g. inversion) and then calculate the output color
// with some basic arithmetic. Alpha combiners can be configured separately but work // with some basic arithmetic. Alpha combiners can be configured separately but work
// analogously. // analogously.
Math::Vec4<u8> combiner_output; Common::Vec4<u8> combiner_output;
Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; Common::Vec4<u8> combiner_buffer = {0, 0, 0, 0};
Math::Vec4<u8> next_combiner_buffer = Common::Vec4<u8> next_combiner_buffer =
Math::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(), Common::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(),
regs.texturing.tev_combiner_buffer_color.g.Value(), regs.texturing.tev_combiner_buffer_color.g.Value(),
regs.texturing.tev_combiner_buffer_color.b.Value(), regs.texturing.tev_combiner_buffer_color.b.Value(),
regs.texturing.tev_combiner_buffer_color.a.Value()) regs.texturing.tev_combiner_buffer_color.a.Value())
.Cast<u8>(); .Cast<u8>();
Math::Vec4<u8> primary_fragment_color = {0, 0, 0, 0}; Common::Vec4<u8> primary_fragment_color = {0, 0, 0, 0};
Math::Vec4<u8> secondary_fragment_color = {0, 0, 0, 0}; Common::Vec4<u8> secondary_fragment_color = {0, 0, 0, 0};
if (!g_state.regs.lighting.disable) { if (!g_state.regs.lighting.disable) {
Math::Quaternion<float> normquat = Common::Quaternion<float> normquat =
Math::Quaternion<float>{ Common::Quaternion<float>{
{GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(), {GetInterpolatedAttribute(v0.quat.x, v1.quat.x, v2.quat.x).ToFloat32(),
GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(), GetInterpolatedAttribute(v0.quat.y, v1.quat.y, v2.quat.y).ToFloat32(),
GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32()}, GetInterpolatedAttribute(v0.quat.z, v1.quat.z, v2.quat.z).ToFloat32()},
@ -464,7 +466,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
} }
.Normalized(); .Normalized();
Math::Vec3<float> view{ Common::Vec3<float> view{
GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(), GetInterpolatedAttribute(v0.view.x, v1.view.x, v2.view.x).ToFloat32(),
GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(), GetInterpolatedAttribute(v0.view.y, v1.view.y, v2.view.y).ToFloat32(),
GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32(), GetInterpolatedAttribute(v0.view.z, v1.view.z, v2.view.z).ToFloat32(),
@ -478,7 +480,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
const auto& tev_stage = tev_stages[tev_stage_index]; const auto& tev_stage = tev_stages[tev_stage_index];
using Source = TexturingRegs::TevStageConfig::Source; using Source = TexturingRegs::TevStageConfig::Source;
auto GetSource = [&](Source source) -> Math::Vec4<u8> { auto GetSource = [&](Source source) -> Common::Vec4<u8> {
switch (source) { switch (source) {
case Source::PrimaryColor: case Source::PrimaryColor:
return primary_color; return primary_color;
@ -505,8 +507,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
return combiner_buffer; return combiner_buffer;
case Source::Constant: case Source::Constant:
return Math::MakeVec(tev_stage.const_r.Value(), tev_stage.const_g.Value(), return Common::MakeVec(tev_stage.const_r.Value(), tev_stage.const_g.Value(),
tev_stage.const_b.Value(), tev_stage.const_a.Value()) tev_stage.const_b.Value(), tev_stage.const_a.Value())
.Cast<u8>(); .Cast<u8>();
case Source::Previous: case Source::Previous:
@ -524,7 +526,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
// stage as input. Hence, we currently don't directly write the result to // stage as input. Hence, we currently don't directly write the result to
// combiner_output.rgb(), but instead store it in a temporary variable until // combiner_output.rgb(), but instead store it in a temporary variable until
// alpha combining has been done. // alpha combining has been done.
Math::Vec3<u8> color_result[3] = { Common::Vec3<u8> color_result[3] = {
GetColorModifier(tev_stage.color_modifier1, GetSource(tev_stage.color_source1)), GetColorModifier(tev_stage.color_modifier1, GetSource(tev_stage.color_source1)),
GetColorModifier(tev_stage.color_modifier2, GetSource(tev_stage.color_source2)), GetColorModifier(tev_stage.color_modifier2, GetSource(tev_stage.color_source2)),
GetColorModifier(tev_stage.color_modifier3, GetSource(tev_stage.color_source3)), GetColorModifier(tev_stage.color_modifier3, GetSource(tev_stage.color_source3)),
@ -631,10 +633,11 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
// store the depth etc. Using float for now until we know more // store the depth etc. Using float for now until we know more
// about Pica datatypes // about Pica datatypes
if (regs.texturing.fog_mode == TexturingRegs::FogMode::Fog) { if (regs.texturing.fog_mode == TexturingRegs::FogMode::Fog) {
const Math::Vec3<u8> fog_color = Math::MakeVec(regs.texturing.fog_color.r.Value(), const Common::Vec3<u8> fog_color =
regs.texturing.fog_color.g.Value(), Common::MakeVec(regs.texturing.fog_color.r.Value(),
regs.texturing.fog_color.b.Value()) regs.texturing.fog_color.g.Value(),
.Cast<u8>(); regs.texturing.fog_color.b.Value())
.Cast<u8>();
// Get index into fog LUT // Get index into fog LUT
float fog_index; float fog_index;
@ -778,7 +781,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
UpdateStencil(stencil_test.action_depth_pass); UpdateStencil(stencil_test.action_depth_pass);
auto dest = GetPixel(x >> 4, y >> 4); auto dest = GetPixel(x >> 4, y >> 4);
Math::Vec4<u8> blend_output = combiner_output; Common::Vec4<u8> blend_output = combiner_output;
if (output_merger.alphablend_enable) { if (output_merger.alphablend_enable) {
auto params = output_merger.alpha_blending; auto params = output_merger.alpha_blending;
@ -787,11 +790,11 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
FramebufferRegs::BlendFactor factor) -> u8 { FramebufferRegs::BlendFactor factor) -> u8 {
DEBUG_ASSERT(channel < 4); DEBUG_ASSERT(channel < 4);
const Math::Vec4<u8> blend_const = const Common::Vec4<u8> blend_const =
Math::MakeVec(output_merger.blend_const.r.Value(), Common::MakeVec(output_merger.blend_const.r.Value(),
output_merger.blend_const.g.Value(), output_merger.blend_const.g.Value(),
output_merger.blend_const.b.Value(), output_merger.blend_const.b.Value(),
output_merger.blend_const.a.Value()) output_merger.blend_const.a.Value())
.Cast<u8>(); .Cast<u8>();
switch (factor) { switch (factor) {
@ -852,15 +855,15 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
return combiner_output[channel]; return combiner_output[channel];
}; };
auto srcfactor = Math::MakeVec(LookupFactor(0, params.factor_source_rgb), auto srcfactor = Common::MakeVec(LookupFactor(0, params.factor_source_rgb),
LookupFactor(1, params.factor_source_rgb), LookupFactor(1, params.factor_source_rgb),
LookupFactor(2, params.factor_source_rgb), LookupFactor(2, params.factor_source_rgb),
LookupFactor(3, params.factor_source_a)); LookupFactor(3, params.factor_source_a));
auto dstfactor = Math::MakeVec(LookupFactor(0, params.factor_dest_rgb), auto dstfactor = Common::MakeVec(LookupFactor(0, params.factor_dest_rgb),
LookupFactor(1, params.factor_dest_rgb), LookupFactor(1, params.factor_dest_rgb),
LookupFactor(2, params.factor_dest_rgb), LookupFactor(2, params.factor_dest_rgb),
LookupFactor(3, params.factor_dest_a)); LookupFactor(3, params.factor_dest_a));
blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor,
params.blend_equation_rgb); params.blend_equation_rgb);
@ -869,13 +872,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
.a(); .a();
} else { } else {
blend_output = blend_output =
Math::MakeVec(LogicOp(combiner_output.r(), dest.r(), output_merger.logic_op), Common::MakeVec(LogicOp(combiner_output.r(), dest.r(), output_merger.logic_op),
LogicOp(combiner_output.g(), dest.g(), output_merger.logic_op), LogicOp(combiner_output.g(), dest.g(), output_merger.logic_op),
LogicOp(combiner_output.b(), dest.b(), output_merger.logic_op), LogicOp(combiner_output.b(), dest.b(), output_merger.logic_op),
LogicOp(combiner_output.a(), dest.a(), output_merger.logic_op)); LogicOp(combiner_output.a(), dest.a(), output_merger.logic_op));
} }
const Math::Vec4<u8> result = { const Common::Vec4<u8> result = {
output_merger.red_enable ? blend_output.r() : dest.r(), output_merger.red_enable ? blend_output.r() : dest.r(),
output_merger.green_enable ? blend_output.g() : dest.g(), output_merger.green_enable ? blend_output.g() : dest.g(),
output_merger.blue_enable ? blend_output.b() : dest.b(), output_merger.blue_enable ? blend_output.b() : dest.b(),

View File

@ -13,7 +13,7 @@ struct Vertex : Shader::OutputVertex {
// Attributes used to store intermediate results // Attributes used to store intermediate results
// position after perspective divide // position after perspective divide
Math::Vec3<float24> screenpos; Common::Vec3<float24> screenpos;
// Linear interpolation // Linear interpolation
// factor: 0=this, 1=vtx // factor: 0=this, 1=vtx

View File

@ -51,8 +51,8 @@ int GetWrappedTexCoord(TexturingRegs::TextureConfig::WrapMode mode, int val, uns
} }
}; };
Math::Vec3<u8> GetColorModifier(TevStageConfig::ColorModifier factor, Common::Vec3<u8> GetColorModifier(TevStageConfig::ColorModifier factor,
const Math::Vec4<u8>& values) { const Common::Vec4<u8>& values) {
using ColorModifier = TevStageConfig::ColorModifier; using ColorModifier = TevStageConfig::ColorModifier;
switch (factor) { switch (factor) {
@ -60,37 +60,37 @@ Math::Vec3<u8> GetColorModifier(TevStageConfig::ColorModifier factor,
return values.rgb(); return values.rgb();
case ColorModifier::OneMinusSourceColor: case ColorModifier::OneMinusSourceColor:
return (Math::Vec3<u8>(255, 255, 255) - values.rgb()).Cast<u8>(); return (Common::Vec3<u8>(255, 255, 255) - values.rgb()).Cast<u8>();
case ColorModifier::SourceAlpha: case ColorModifier::SourceAlpha:
return values.aaa(); return values.aaa();
case ColorModifier::OneMinusSourceAlpha: case ColorModifier::OneMinusSourceAlpha:
return (Math::Vec3<u8>(255, 255, 255) - values.aaa()).Cast<u8>(); return (Common::Vec3<u8>(255, 255, 255) - values.aaa()).Cast<u8>();
case ColorModifier::SourceRed: case ColorModifier::SourceRed:
return values.rrr(); return values.rrr();
case ColorModifier::OneMinusSourceRed: case ColorModifier::OneMinusSourceRed:
return (Math::Vec3<u8>(255, 255, 255) - values.rrr()).Cast<u8>(); return (Common::Vec3<u8>(255, 255, 255) - values.rrr()).Cast<u8>();
case ColorModifier::SourceGreen: case ColorModifier::SourceGreen:
return values.ggg(); return values.ggg();
case ColorModifier::OneMinusSourceGreen: case ColorModifier::OneMinusSourceGreen:
return (Math::Vec3<u8>(255, 255, 255) - values.ggg()).Cast<u8>(); return (Common::Vec3<u8>(255, 255, 255) - values.ggg()).Cast<u8>();
case ColorModifier::SourceBlue: case ColorModifier::SourceBlue:
return values.bbb(); return values.bbb();
case ColorModifier::OneMinusSourceBlue: case ColorModifier::OneMinusSourceBlue:
return (Math::Vec3<u8>(255, 255, 255) - values.bbb()).Cast<u8>(); return (Common::Vec3<u8>(255, 255, 255) - values.bbb()).Cast<u8>();
} }
UNREACHABLE(); UNREACHABLE();
}; };
u8 GetAlphaModifier(TevStageConfig::AlphaModifier factor, const Math::Vec4<u8>& values) { u8 GetAlphaModifier(TevStageConfig::AlphaModifier factor, const Common::Vec4<u8>& values) {
using AlphaModifier = TevStageConfig::AlphaModifier; using AlphaModifier = TevStageConfig::AlphaModifier;
switch (factor) { switch (factor) {
@ -122,7 +122,7 @@ u8 GetAlphaModifier(TevStageConfig::AlphaModifier factor, const Math::Vec4<u8>&
UNREACHABLE(); UNREACHABLE();
}; };
Math::Vec3<u8> ColorCombine(TevStageConfig::Operation op, const Math::Vec3<u8> input[3]) { Common::Vec3<u8> ColorCombine(TevStageConfig::Operation op, const Common::Vec3<u8> input[3]) {
using Operation = TevStageConfig::Operation; using Operation = TevStageConfig::Operation;
switch (op) { switch (op) {
@ -144,7 +144,7 @@ Math::Vec3<u8> ColorCombine(TevStageConfig::Operation op, const Math::Vec3<u8> i
// TODO(bunnei): Verify that the color conversion from (float) 0.5f to // TODO(bunnei): Verify that the color conversion from (float) 0.5f to
// (byte) 128 is correct // (byte) 128 is correct
auto result = auto result =
input[0].Cast<int>() + input[1].Cast<int>() - Math::MakeVec<int>(128, 128, 128); input[0].Cast<int>() + input[1].Cast<int>() - Common::MakeVec<int>(128, 128, 128);
result.r() = std::clamp<int>(result.r(), 0, 255); result.r() = std::clamp<int>(result.r(), 0, 255);
result.g() = std::clamp<int>(result.g(), 0, 255); result.g() = std::clamp<int>(result.g(), 0, 255);
result.b() = std::clamp<int>(result.b(), 0, 255); result.b() = std::clamp<int>(result.b(), 0, 255);
@ -153,7 +153,7 @@ Math::Vec3<u8> ColorCombine(TevStageConfig::Operation op, const Math::Vec3<u8> i
case Operation::Lerp: case Operation::Lerp:
return ((input[0] * input[2] + return ((input[0] * input[2] +
input[1] * (Math::MakeVec<u8>(255, 255, 255) - input[2]).Cast<u8>()) / input[1] * (Common::MakeVec<u8>(255, 255, 255) - input[2]).Cast<u8>()) /
255) 255)
.Cast<u8>(); .Cast<u8>();

View File

@ -12,14 +12,14 @@ namespace Pica::Rasterizer {
int GetWrappedTexCoord(TexturingRegs::TextureConfig::WrapMode mode, int val, unsigned size); int GetWrappedTexCoord(TexturingRegs::TextureConfig::WrapMode mode, int val, unsigned size);
Math::Vec3<u8> GetColorModifier(TexturingRegs::TevStageConfig::ColorModifier factor, Common::Vec3<u8> GetColorModifier(TexturingRegs::TevStageConfig::ColorModifier factor,
const Math::Vec4<u8>& values); const Common::Vec4<u8>& values);
u8 GetAlphaModifier(TexturingRegs::TevStageConfig::AlphaModifier factor, u8 GetAlphaModifier(TexturingRegs::TevStageConfig::AlphaModifier factor,
const Math::Vec4<u8>& values); const Common::Vec4<u8>& values);
Math::Vec3<u8> ColorCombine(TexturingRegs::TevStageConfig::Operation op, Common::Vec3<u8> ColorCombine(TexturingRegs::TevStageConfig::Operation op,
const Math::Vec3<u8> input[3]); const Common::Vec3<u8> input[3]);
u8 AlphaCombine(TexturingRegs::TevStageConfig::Operation op, const std::array<u8, 3>& input); u8 AlphaCombine(TexturingRegs::TevStageConfig::Operation op, const std::array<u8, 3>& input);

View File

@ -69,14 +69,14 @@ union ETC1Tile {
BitField<60, 4, u64> r1; BitField<60, 4, u64> r1;
} separate; } separate;
const Math::Vec3<u8> GetRGB(unsigned int x, unsigned int y) const { const Common::Vec3<u8> GetRGB(unsigned int x, unsigned int y) const {
int texel = 4 * x + y; int texel = 4 * x + y;
if (flip) if (flip)
std::swap(x, y); std::swap(x, y);
// Lookup base value // Lookup base value
Math::Vec3<int> ret; Common::Vec3<int> ret;
if (differential_mode) { if (differential_mode) {
ret.r() = static_cast<int>(differential.r); ret.r() = static_cast<int>(differential.r);
ret.g() = static_cast<int>(differential.g); ret.g() = static_cast<int>(differential.g);
@ -119,7 +119,7 @@ union ETC1Tile {
} // anonymous namespace } // anonymous namespace
Math::Vec3<u8> SampleETC1Subtile(u64 value, unsigned int x, unsigned int y) { Common::Vec3<u8> SampleETC1Subtile(u64 value, unsigned int x, unsigned int y) {
ETC1Tile tile{value}; ETC1Tile tile{value};
return tile.GetRGB(x, y); return tile.GetRGB(x, y);
} }

View File

@ -9,6 +9,6 @@
namespace Pica::Texture { namespace Pica::Texture {
Math::Vec3<u8> SampleETC1Subtile(u64 value, unsigned int x, unsigned int y); Common::Vec3<u8> SampleETC1Subtile(u64 value, unsigned int x, unsigned int y);
} // namespace Pica::Texture } // namespace Pica::Texture

View File

@ -56,8 +56,8 @@ size_t CalculateTileSize(TextureFormat format) {
} }
} }
Math::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y, Common::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y,
const TextureInfo& info, bool disable_alpha) { const TextureInfo& info, bool disable_alpha) {
// Coordinate in tiles // Coordinate in tiles
const unsigned int coarse_x = x / 8; const unsigned int coarse_x = x / 8;
const unsigned int coarse_y = y / 8; const unsigned int coarse_y = y / 8;
@ -71,8 +71,8 @@ Math::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y,
return LookupTexelInTile(tile, fine_x, fine_y, info, disable_alpha); return LookupTexelInTile(tile, fine_x, fine_y, info, disable_alpha);
} }
Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int y, Common::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int y,
const TextureInfo& info, bool disable_alpha) { const TextureInfo& info, bool disable_alpha) {
DEBUG_ASSERT(x < 8); DEBUG_ASSERT(x < 8);
DEBUG_ASSERT(y < 8); DEBUG_ASSERT(y < 8);
@ -200,8 +200,8 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
u64_le subtile_data; u64_le subtile_data;
memcpy(&subtile_data, subtile_ptr, sizeof(u64)); memcpy(&subtile_data, subtile_ptr, sizeof(u64));
return Math::MakeVec(SampleETC1Subtile(subtile_data, x, y), return Common::MakeVec(SampleETC1Subtile(subtile_data, x, y),
disable_alpha ? (u8)255 : alpha); disable_alpha ? (u8)255 : alpha);
} }
default: default:

View File

@ -40,8 +40,8 @@ struct TextureInfo {
* channel. * channel.
* @todo Eventually we should get rid of the disable_alpha parameter. * @todo Eventually we should get rid of the disable_alpha parameter.
*/ */
Math::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y, Common::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y,
const TextureInfo& info, bool disable_alpha = false); const TextureInfo& info, bool disable_alpha = false);
/** /**
* Looks up a texel from a single 8x8 texture tile. * Looks up a texel from a single 8x8 texture tile.
@ -52,7 +52,7 @@ Math::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y,
* @param disable_alpha Used for debugging. Sets the result alpha to 255 and either discards the * @param disable_alpha Used for debugging. Sets the result alpha to 255 and either discards the
* real alpha or inserts it in an otherwise unused channel. * real alpha or inserts it in an otherwise unused channel.
*/ */
Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int y, Common::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int y,
const TextureInfo& info, bool disable_alpha); const TextureInfo& info, bool disable_alpha);
} // namespace Pica::Texture } // namespace Pica::Texture