diff options
Diffstat (limited to 'src/core/hw/gpu.h')
| -rw-r--r-- | src/core/hw/gpu.h | 84 |
1 files changed, 44 insertions, 40 deletions
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index da4c345b4..077b6255f 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h | |||
| @@ -17,7 +17,8 @@ namespace GPU { | |||
| 17 | // Returns index corresponding to the Regs member labeled by field_name | 17 | // Returns index corresponding to the Regs member labeled by field_name |
| 18 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions | 18 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions |
| 19 | // when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). | 19 | // when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). |
| 20 | // For details cf. https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | 20 | // For details cf. |
| 21 | // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | ||
| 21 | // Hopefully, this will be fixed sometime in the future. | 22 | // Hopefully, this will be fixed sometime in the future. |
| 22 | // For lack of better alternatives, we currently hardcode the offsets when constant | 23 | // For lack of better alternatives, we currently hardcode the offsets when constant |
| 23 | // expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts | 24 | // expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts |
| @@ -30,8 +31,9 @@ namespace GPU { | |||
| 30 | // really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX | 31 | // really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX |
| 31 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected | 32 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected |
| 32 | // field offset. Otherwise, the compiler will fail to compile this code. | 33 | // field offset. Otherwise, the compiler will fail to compile this code. |
| 33 | #define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ | 34 | #define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ |
| 34 | ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type)GPU_REG_INDEX(field_name)) | 35 | ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type) \ |
| 36 | GPU_REG_INDEX(field_name)) | ||
| 35 | #endif | 37 | #endif |
| 36 | 38 | ||
| 37 | // MMIO region 0x1EFxxxxx | 39 | // MMIO region 0x1EFxxxxx |
| @@ -44,18 +46,18 @@ struct Regs { | |||
| 44 | // support for that. | 46 | // support for that. |
| 45 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) | 47 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) |
| 46 | #else | 48 | #else |
| 47 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ | 49 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ |
| 48 | static_assert(sizeof(name) == size_in_bytes, \ | 50 | static_assert(sizeof(name) == size_in_bytes, \ |
| 49 | "Structure size and register block length don't match") | 51 | "Structure size and register block length don't match") |
| 50 | #endif | 52 | #endif |
| 51 | 53 | ||
| 52 | // Components are laid out in reverse byte order, most significant bits first. | 54 | // Components are laid out in reverse byte order, most significant bits first. |
| 53 | enum class PixelFormat : u32 { | 55 | enum class PixelFormat : u32 { |
| 54 | RGBA8 = 0, | 56 | RGBA8 = 0, |
| 55 | RGB8 = 1, | 57 | RGB8 = 1, |
| 56 | RGB565 = 2, | 58 | RGB565 = 2, |
| 57 | RGB5A1 = 3, | 59 | RGB5A1 = 3, |
| 58 | RGBA4 = 4, | 60 | RGBA4 = 4, |
| 59 | }; | 61 | }; |
| 60 | 62 | ||
| 61 | /** | 63 | /** |
| @@ -88,8 +90,8 @@ struct Regs { | |||
| 88 | BitField<0, 16, u32> value_16bit; | 90 | BitField<0, 16, u32> value_16bit; |
| 89 | 91 | ||
| 90 | // TODO: Verify component order | 92 | // TODO: Verify component order |
| 91 | BitField< 0, 8, u32> value_24bit_r; | 93 | BitField<0, 8, u32> value_24bit_r; |
| 92 | BitField< 8, 8, u32> value_24bit_g; | 94 | BitField<8, 8, u32> value_24bit_g; |
| 93 | BitField<16, 8, u32> value_24bit_b; | 95 | BitField<16, 8, u32> value_24bit_b; |
| 94 | }; | 96 | }; |
| 95 | 97 | ||
| @@ -126,7 +128,7 @@ struct Regs { | |||
| 126 | union { | 128 | union { |
| 127 | u32 size; | 129 | u32 size; |
| 128 | 130 | ||
| 129 | BitField< 0, 16, u32> width; | 131 | BitField<0, 16, u32> width; |
| 130 | BitField<16, 16, u32> height; | 132 | BitField<16, 16, u32> height; |
| 131 | }; | 133 | }; |
| 132 | 134 | ||
| @@ -138,7 +140,7 @@ struct Regs { | |||
| 138 | union { | 140 | union { |
| 139 | u32 format; | 141 | u32 format; |
| 140 | 142 | ||
| 141 | BitField< 0, 3, PixelFormat> color_format; | 143 | BitField<0, 3, PixelFormat> color_format; |
| 142 | }; | 144 | }; |
| 143 | 145 | ||
| 144 | INSERT_PADDING_WORDS(0x1); | 146 | INSERT_PADDING_WORDS(0x1); |
| @@ -180,35 +182,37 @@ struct Regs { | |||
| 180 | union { | 182 | union { |
| 181 | u32 output_size; | 183 | u32 output_size; |
| 182 | 184 | ||
| 183 | BitField< 0, 16, u32> output_width; | 185 | BitField<0, 16, u32> output_width; |
| 184 | BitField<16, 16, u32> output_height; | 186 | BitField<16, 16, u32> output_height; |
| 185 | }; | 187 | }; |
| 186 | 188 | ||
| 187 | union { | 189 | union { |
| 188 | u32 input_size; | 190 | u32 input_size; |
| 189 | 191 | ||
| 190 | BitField< 0, 16, u32> input_width; | 192 | BitField<0, 16, u32> input_width; |
| 191 | BitField<16, 16, u32> input_height; | 193 | BitField<16, 16, u32> input_height; |
| 192 | }; | 194 | }; |
| 193 | 195 | ||
| 194 | enum ScalingMode : u32 { | 196 | enum ScalingMode : u32 { |
| 195 | NoScale = 0, // Doesn't scale the image | 197 | NoScale = 0, // Doesn't scale the image |
| 196 | ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter | 198 | ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter |
| 197 | ScaleXY = 2, // Downscales the image in half in both the X and Y axes and applies a box filter | 199 | ScaleXY = |
| 200 | 2, // Downscales the image in half in both the X and Y axes and applies a box filter | ||
| 198 | }; | 201 | }; |
| 199 | 202 | ||
| 200 | union { | 203 | union { |
| 201 | u32 flags; | 204 | u32 flags; |
| 202 | 205 | ||
| 203 | BitField< 0, 1, u32> flip_vertically; // flips input data vertically | 206 | BitField<0, 1, u32> flip_vertically; // flips input data vertically |
| 204 | BitField< 1, 1, u32> input_linear; // Converts from linear to tiled format | 207 | BitField<1, 1, u32> input_linear; // Converts from linear to tiled format |
| 205 | BitField< 2, 1, u32> crop_input_lines; | 208 | BitField<2, 1, u32> crop_input_lines; |
| 206 | BitField< 3, 1, u32> is_texture_copy; // Copies the data without performing any processing and respecting texture copy fields | 209 | BitField<3, 1, u32> is_texture_copy; // Copies the data without performing any |
| 207 | BitField< 5, 1, u32> dont_swizzle; | 210 | // processing and respecting texture copy fields |
| 208 | BitField< 8, 3, PixelFormat> input_format; | 211 | BitField<5, 1, u32> dont_swizzle; |
| 212 | BitField<8, 3, PixelFormat> input_format; | ||
| 209 | BitField<12, 3, PixelFormat> output_format; | 213 | BitField<12, 3, PixelFormat> output_format; |
| 210 | /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. | 214 | /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. |
| 211 | BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented | 215 | BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented |
| 212 | BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer | 216 | BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer |
| 213 | }; | 217 | }; |
| 214 | 218 | ||
| @@ -225,14 +229,14 @@ struct Regs { | |||
| 225 | union { | 229 | union { |
| 226 | u32 input_size; | 230 | u32 input_size; |
| 227 | 231 | ||
| 228 | BitField< 0, 16, u32> input_width; | 232 | BitField<0, 16, u32> input_width; |
| 229 | BitField<16, 16, u32> input_gap; | 233 | BitField<16, 16, u32> input_gap; |
| 230 | }; | 234 | }; |
| 231 | 235 | ||
| 232 | union { | 236 | union { |
| 233 | u32 output_size; | 237 | u32 output_size; |
| 234 | 238 | ||
| 235 | BitField< 0, 16, u32> output_width; | 239 | BitField<0, 16, u32> output_width; |
| 236 | BitField<16, 16, u32> output_gap; | 240 | BitField<16, 16, u32> output_gap; |
| 237 | }; | 241 | }; |
| 238 | } texture_copy; | 242 | } texture_copy; |
| @@ -267,12 +271,12 @@ struct Regs { | |||
| 267 | return sizeof(Regs) / sizeof(u32); | 271 | return sizeof(Regs) / sizeof(u32); |
| 268 | } | 272 | } |
| 269 | 273 | ||
| 270 | const u32& operator [] (int index) const { | 274 | const u32& operator[](int index) const { |
| 271 | const u32* content = reinterpret_cast<const u32*>(this); | 275 | const u32* content = reinterpret_cast<const u32*>(this); |
| 272 | return content[index]; | 276 | return content[index]; |
| 273 | } | 277 | } |
| 274 | 278 | ||
| 275 | u32& operator [] (int index) { | 279 | u32& operator[](int index) { |
| 276 | u32* content = reinterpret_cast<u32*>(this); | 280 | u32* content = reinterpret_cast<u32*>(this); |
| 277 | return content[index]; | 281 | return content[index]; |
| 278 | } | 282 | } |
| @@ -294,28 +298,29 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan | |||
| 294 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | 298 | // is technically allowed since C++11. This macro should be enabled once MSVC adds |
| 295 | // support for that. | 299 | // support for that. |
| 296 | #ifndef _MSC_VER | 300 | #ifndef _MSC_VER |
| 297 | #define ASSERT_REG_POSITION(field_name, position) \ | 301 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 298 | static_assert(offsetof(Regs, field_name) == position * 4, \ | 302 | static_assert(offsetof(Regs, field_name) == position * 4, \ |
| 299 | "Field "#field_name" has invalid position") | 303 | "Field " #field_name " has invalid position") |
| 300 | 304 | ||
| 301 | ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); | 305 | ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); |
| 302 | ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); | 306 | ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); |
| 303 | ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); | 307 | ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); |
| 304 | ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); | 308 | ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); |
| 305 | ASSERT_REG_POSITION(display_transfer_config, 0x00300); | 309 | ASSERT_REG_POSITION(display_transfer_config, 0x00300); |
| 306 | ASSERT_REG_POSITION(command_processor_config, 0x00638); | 310 | ASSERT_REG_POSITION(command_processor_config, 0x00638); |
| 307 | 311 | ||
| 308 | #undef ASSERT_REG_POSITION | 312 | #undef ASSERT_REG_POSITION |
| 309 | #endif // !defined(_MSC_VER) | 313 | #endif // !defined(_MSC_VER) |
| 310 | 314 | ||
| 311 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. | 315 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value |
| 316 | // anyway. | ||
| 312 | static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); | 317 | static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); |
| 313 | 318 | ||
| 314 | extern Regs g_regs; | 319 | extern Regs g_regs; |
| 315 | extern bool g_skip_frame; | 320 | extern bool g_skip_frame; |
| 316 | 321 | ||
| 317 | template <typename T> | 322 | template <typename T> |
| 318 | void Read(T &var, const u32 addr); | 323 | void Read(T& var, const u32 addr); |
| 319 | 324 | ||
| 320 | template <typename T> | 325 | template <typename T> |
| 321 | void Write(u32 addr, const T data); | 326 | void Write(u32 addr, const T data); |
| @@ -326,5 +331,4 @@ void Init(); | |||
| 326 | /// Shutdown hardware | 331 | /// Shutdown hardware |
| 327 | void Shutdown(); | 332 | void Shutdown(); |
| 328 | 333 | ||
| 329 | |||
| 330 | } // namespace | 334 | } // namespace |