mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									db58652680
								
							
						
					
					
						commit
						643472e24a
					
				
					 40 changed files with 309 additions and 301 deletions
				
			
		|  | @ -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())); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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)}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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>(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -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: | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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() { | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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])}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
|  |  | ||||||
|  | @ -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}; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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]); | ||||||
|  |  | ||||||
|  | @ -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>); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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.
 | ||||||
|  |  | ||||||
|  | @ -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]}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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(), | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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>(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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: | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue