common/vector_math: Move Vec[x] types into the Common namespace

These types are within the common library, so they should be using the
Common namespace.
This commit is contained in:
Lioncash 2019-02-26 22:38:34 -05:00 committed by fearlessTobi
parent db58652680
commit 643472e24a
40 changed files with 309 additions and 301 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

@ -11,8 +11,8 @@ 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,11 +38,11 @@ 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)};
} }

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

@ -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) {
@ -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,7 +87,7 @@ private:
void MotionEmuThread() { void MotionEmuThread() {
auto update_time = std::chrono::steady_clock::now(); auto update_time = std::chrono::steady_clock::now();
Common::Quaternion<float> q = Common::MakeQuaternion(Math::Vec3<float>(), 0); Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
Common::Quaternion<float> old_q; Common::Quaternion<float> old_q;
while (!shutdown_event.WaitUntil(update_time)) { while (!shutdown_event.WaitUntil(update_time)) {
@ -98,14 +98,14 @@ 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 = Common::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;
@ -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);
@ -217,8 +217,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
success_callback(); success_callback();
else else
failure_callback(); failure_callback();
}) }).detach();
.detach();
} }
CalibrationConfigurationJob::CalibrationConfigurationJob( CalibrationConfigurationJob::CalibrationConfigurationJob(
@ -269,8 +268,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
complete_event.Wait(); complete_event.Wait();
socket.Stop(); socket.Stop();
worker_thread.join(); worker_thread.join();
}) }).detach();
.detach();
} }
CalibrationConfigurationJob::~CalibrationConfigurationJob() { CalibrationConfigurationJob::~CalibrationConfigurationJob() {

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,

View file

@ -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};

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,7 @@ 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