|
@@ -19,6 +19,7 @@
|
|
|
#include "common/logging/log.h"
|
|
#include "common/logging/log.h"
|
|
|
#include "common/vector_math.h"
|
|
#include "common/vector_math.h"
|
|
|
#include "video_core/regs_rasterizer.h"
|
|
#include "video_core/regs_rasterizer.h"
|
|
|
|
|
+#include "video_core/regs_texturing.h"
|
|
|
|
|
|
|
|
namespace Pica {
|
|
namespace Pica {
|
|
|
|
|
|
|
@@ -49,81 +50,7 @@ struct Regs {
|
|
|
u32 trigger_irq;
|
|
u32 trigger_irq;
|
|
|
INSERT_PADDING_WORDS(0x2f);
|
|
INSERT_PADDING_WORDS(0x2f);
|
|
|
RasterizerRegs rasterizer;
|
|
RasterizerRegs rasterizer;
|
|
|
-
|
|
|
|
|
- struct TextureConfig {
|
|
|
|
|
- enum TextureType : u32 {
|
|
|
|
|
- Texture2D = 0,
|
|
|
|
|
- TextureCube = 1,
|
|
|
|
|
- Shadow2D = 2,
|
|
|
|
|
- Projection2D = 3,
|
|
|
|
|
- ShadowCube = 4,
|
|
|
|
|
- Disabled = 5,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- enum WrapMode : u32 {
|
|
|
|
|
- ClampToEdge = 0,
|
|
|
|
|
- ClampToBorder = 1,
|
|
|
|
|
- Repeat = 2,
|
|
|
|
|
- MirroredRepeat = 3,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- enum TextureFilter : u32 {
|
|
|
|
|
- Nearest = 0,
|
|
|
|
|
- Linear = 1,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 raw;
|
|
|
|
|
- BitField<0, 8, u32> r;
|
|
|
|
|
- BitField<8, 8, u32> g;
|
|
|
|
|
- BitField<16, 8, u32> b;
|
|
|
|
|
- BitField<24, 8, u32> a;
|
|
|
|
|
- } border_color;
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- BitField<0, 16, u32> height;
|
|
|
|
|
- BitField<16, 16, u32> width;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- BitField<1, 1, TextureFilter> mag_filter;
|
|
|
|
|
- BitField<2, 1, TextureFilter> min_filter;
|
|
|
|
|
- BitField<8, 2, WrapMode> wrap_t;
|
|
|
|
|
- BitField<12, 2, WrapMode> wrap_s;
|
|
|
|
|
- BitField<28, 2, TextureType>
|
|
|
|
|
- type; ///< @note Only valid for texture 0 according to 3DBrew.
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- INSERT_PADDING_WORDS(0x1);
|
|
|
|
|
-
|
|
|
|
|
- u32 address;
|
|
|
|
|
-
|
|
|
|
|
- u32 GetPhysicalAddress() const {
|
|
|
|
|
- return DecodeAddressRegister(address);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // texture1 and texture2 store the texture format directly after the address
|
|
|
|
|
- // whereas texture0 inserts some additional flags inbetween.
|
|
|
|
|
- // Hence, we store the format separately so that all other parameters can be described
|
|
|
|
|
- // in a single structure.
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- enum class TextureFormat : u32 {
|
|
|
|
|
- RGBA8 = 0,
|
|
|
|
|
- RGB8 = 1,
|
|
|
|
|
- RGB5A1 = 2,
|
|
|
|
|
- RGB565 = 3,
|
|
|
|
|
- RGBA4 = 4,
|
|
|
|
|
- IA8 = 5,
|
|
|
|
|
- RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
|
|
|
|
|
- I8 = 7,
|
|
|
|
|
- A8 = 8,
|
|
|
|
|
- IA4 = 9,
|
|
|
|
|
- I4 = 10,
|
|
|
|
|
- A4 = 11,
|
|
|
|
|
- ETC1 = 12, // compressed
|
|
|
|
|
- ETC1A4 = 13, // compressed
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ TexturingRegs texturing;
|
|
|
|
|
|
|
|
enum class LogicOp : u32 {
|
|
enum class LogicOp : u32 {
|
|
|
Clear = 0,
|
|
Clear = 0,
|
|
@@ -144,239 +71,6 @@ struct Regs {
|
|
|
OrInverted = 15,
|
|
OrInverted = 15,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- static unsigned NibblesPerPixel(TextureFormat format) {
|
|
|
|
|
- switch (format) {
|
|
|
|
|
- case TextureFormat::RGBA8:
|
|
|
|
|
- return 8;
|
|
|
|
|
-
|
|
|
|
|
- case TextureFormat::RGB8:
|
|
|
|
|
- return 6;
|
|
|
|
|
-
|
|
|
|
|
- case TextureFormat::RGB5A1:
|
|
|
|
|
- case TextureFormat::RGB565:
|
|
|
|
|
- case TextureFormat::RGBA4:
|
|
|
|
|
- case TextureFormat::IA8:
|
|
|
|
|
- case TextureFormat::RG8:
|
|
|
|
|
- return 4;
|
|
|
|
|
-
|
|
|
|
|
- case TextureFormat::I4:
|
|
|
|
|
- case TextureFormat::A4:
|
|
|
|
|
- return 1;
|
|
|
|
|
-
|
|
|
|
|
- case TextureFormat::I8:
|
|
|
|
|
- case TextureFormat::A8:
|
|
|
|
|
- case TextureFormat::IA4:
|
|
|
|
|
- return 2;
|
|
|
|
|
-
|
|
|
|
|
- default: // placeholder for yet unknown formats
|
|
|
|
|
- UNIMPLEMENTED();
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- BitField<0, 1, u32> texture0_enable;
|
|
|
|
|
- BitField<1, 1, u32> texture1_enable;
|
|
|
|
|
- BitField<2, 1, u32> texture2_enable;
|
|
|
|
|
- };
|
|
|
|
|
- TextureConfig texture0;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x8);
|
|
|
|
|
- BitField<0, 4, TextureFormat> texture0_format;
|
|
|
|
|
- BitField<0, 1, u32> fragment_lighting_enable;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x1);
|
|
|
|
|
- TextureConfig texture1;
|
|
|
|
|
- BitField<0, 4, TextureFormat> texture1_format;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x2);
|
|
|
|
|
- TextureConfig texture2;
|
|
|
|
|
- BitField<0, 4, TextureFormat> texture2_format;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x21);
|
|
|
|
|
-
|
|
|
|
|
- struct FullTextureConfig {
|
|
|
|
|
- const bool enabled;
|
|
|
|
|
- const TextureConfig config;
|
|
|
|
|
- const TextureFormat format;
|
|
|
|
|
- };
|
|
|
|
|
- const std::array<FullTextureConfig, 3> GetTextures() const {
|
|
|
|
|
- return {{
|
|
|
|
|
- {texture0_enable.ToBool(), texture0, texture0_format},
|
|
|
|
|
- {texture1_enable.ToBool(), texture1, texture1_format},
|
|
|
|
|
- {texture2_enable.ToBool(), texture2, texture2_format},
|
|
|
|
|
- }};
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 0xc0-0xff: Texture Combiner (akin to glTexEnv)
|
|
|
|
|
- struct TevStageConfig {
|
|
|
|
|
- enum class Source : u32 {
|
|
|
|
|
- PrimaryColor = 0x0,
|
|
|
|
|
- PrimaryFragmentColor = 0x1,
|
|
|
|
|
- SecondaryFragmentColor = 0x2,
|
|
|
|
|
-
|
|
|
|
|
- Texture0 = 0x3,
|
|
|
|
|
- Texture1 = 0x4,
|
|
|
|
|
- Texture2 = 0x5,
|
|
|
|
|
- Texture3 = 0x6,
|
|
|
|
|
-
|
|
|
|
|
- PreviousBuffer = 0xd,
|
|
|
|
|
- Constant = 0xe,
|
|
|
|
|
- Previous = 0xf,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- enum class ColorModifier : u32 {
|
|
|
|
|
- SourceColor = 0x0,
|
|
|
|
|
- OneMinusSourceColor = 0x1,
|
|
|
|
|
- SourceAlpha = 0x2,
|
|
|
|
|
- OneMinusSourceAlpha = 0x3,
|
|
|
|
|
- SourceRed = 0x4,
|
|
|
|
|
- OneMinusSourceRed = 0x5,
|
|
|
|
|
-
|
|
|
|
|
- SourceGreen = 0x8,
|
|
|
|
|
- OneMinusSourceGreen = 0x9,
|
|
|
|
|
-
|
|
|
|
|
- SourceBlue = 0xc,
|
|
|
|
|
- OneMinusSourceBlue = 0xd,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- enum class AlphaModifier : u32 {
|
|
|
|
|
- SourceAlpha = 0x0,
|
|
|
|
|
- OneMinusSourceAlpha = 0x1,
|
|
|
|
|
- SourceRed = 0x2,
|
|
|
|
|
- OneMinusSourceRed = 0x3,
|
|
|
|
|
- SourceGreen = 0x4,
|
|
|
|
|
- OneMinusSourceGreen = 0x5,
|
|
|
|
|
- SourceBlue = 0x6,
|
|
|
|
|
- OneMinusSourceBlue = 0x7,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- enum class Operation : u32 {
|
|
|
|
|
- Replace = 0,
|
|
|
|
|
- Modulate = 1,
|
|
|
|
|
- Add = 2,
|
|
|
|
|
- AddSigned = 3,
|
|
|
|
|
- Lerp = 4,
|
|
|
|
|
- Subtract = 5,
|
|
|
|
|
- Dot3_RGB = 6,
|
|
|
|
|
-
|
|
|
|
|
- MultiplyThenAdd = 8,
|
|
|
|
|
- AddThenMultiply = 9,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 sources_raw;
|
|
|
|
|
- BitField<0, 4, Source> color_source1;
|
|
|
|
|
- BitField<4, 4, Source> color_source2;
|
|
|
|
|
- BitField<8, 4, Source> color_source3;
|
|
|
|
|
- BitField<16, 4, Source> alpha_source1;
|
|
|
|
|
- BitField<20, 4, Source> alpha_source2;
|
|
|
|
|
- BitField<24, 4, Source> alpha_source3;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 modifiers_raw;
|
|
|
|
|
- BitField<0, 4, ColorModifier> color_modifier1;
|
|
|
|
|
- BitField<4, 4, ColorModifier> color_modifier2;
|
|
|
|
|
- BitField<8, 4, ColorModifier> color_modifier3;
|
|
|
|
|
- BitField<12, 3, AlphaModifier> alpha_modifier1;
|
|
|
|
|
- BitField<16, 3, AlphaModifier> alpha_modifier2;
|
|
|
|
|
- BitField<20, 3, AlphaModifier> alpha_modifier3;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 ops_raw;
|
|
|
|
|
- BitField<0, 4, Operation> color_op;
|
|
|
|
|
- BitField<16, 4, Operation> alpha_op;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 const_color;
|
|
|
|
|
- BitField<0, 8, u32> const_r;
|
|
|
|
|
- BitField<8, 8, u32> const_g;
|
|
|
|
|
- BitField<16, 8, u32> const_b;
|
|
|
|
|
- BitField<24, 8, u32> const_a;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 scales_raw;
|
|
|
|
|
- BitField<0, 2, u32> color_scale;
|
|
|
|
|
- BitField<16, 2, u32> alpha_scale;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- inline unsigned GetColorMultiplier() const {
|
|
|
|
|
- return (color_scale < 3) ? (1 << color_scale) : 1;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- inline unsigned GetAlphaMultiplier() const {
|
|
|
|
|
- return (alpha_scale < 3) ? (1 << alpha_scale) : 1;
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- TevStageConfig tev_stage0;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x3);
|
|
|
|
|
- TevStageConfig tev_stage1;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x3);
|
|
|
|
|
- TevStageConfig tev_stage2;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x3);
|
|
|
|
|
- TevStageConfig tev_stage3;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x3);
|
|
|
|
|
-
|
|
|
|
|
- enum class FogMode : u32 {
|
|
|
|
|
- None = 0,
|
|
|
|
|
- Fog = 5,
|
|
|
|
|
- Gas = 7,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- BitField<0, 3, FogMode> fog_mode;
|
|
|
|
|
- BitField<16, 1, u32> fog_flip;
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
|
|
|
|
|
- // these masks are set
|
|
|
|
|
- BitField<8, 4, u32> update_mask_rgb;
|
|
|
|
|
- BitField<12, 4, u32> update_mask_a;
|
|
|
|
|
-
|
|
|
|
|
- bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
|
|
|
|
|
- return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
|
|
|
|
|
- return (stage_index < 4) && (update_mask_a & (1 << stage_index));
|
|
|
|
|
- }
|
|
|
|
|
- } tev_combiner_buffer_input;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 raw;
|
|
|
|
|
- BitField<0, 8, u32> r;
|
|
|
|
|
- BitField<8, 8, u32> g;
|
|
|
|
|
- BitField<16, 8, u32> b;
|
|
|
|
|
- } fog_color;
|
|
|
|
|
-
|
|
|
|
|
- INSERT_PADDING_WORDS(0x4);
|
|
|
|
|
-
|
|
|
|
|
- BitField<0, 16, u32> fog_lut_offset;
|
|
|
|
|
-
|
|
|
|
|
- INSERT_PADDING_WORDS(0x1);
|
|
|
|
|
-
|
|
|
|
|
- u32 fog_lut_data[8];
|
|
|
|
|
-
|
|
|
|
|
- TevStageConfig tev_stage4;
|
|
|
|
|
- INSERT_PADDING_WORDS(0x3);
|
|
|
|
|
- TevStageConfig tev_stage5;
|
|
|
|
|
-
|
|
|
|
|
- union {
|
|
|
|
|
- u32 raw;
|
|
|
|
|
- BitField<0, 8, u32> r;
|
|
|
|
|
- BitField<8, 8, u32> g;
|
|
|
|
|
- BitField<16, 8, u32> b;
|
|
|
|
|
- BitField<24, 8, u32> a;
|
|
|
|
|
- } tev_combiner_buffer_color;
|
|
|
|
|
-
|
|
|
|
|
- INSERT_PADDING_WORDS(0x2);
|
|
|
|
|
-
|
|
|
|
|
- const std::array<Regs::TevStageConfig, 6> GetTevStages() const {
|
|
|
|
|
- return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}};
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
enum class BlendEquation : u32 {
|
|
enum class BlendEquation : u32 {
|
|
|
Add = 0,
|
|
Add = 0,
|
|
|
Subtract = 1,
|
|
Subtract = 1,
|
|
@@ -1241,26 +935,28 @@ ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65);
|
|
|
ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68);
|
|
ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68);
|
|
|
ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D);
|
|
ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D);
|
|
|
|
|
|
|
|
-ASSERT_REG_POSITION(texture0_enable, 0x80);
|
|
|
|
|
-ASSERT_REG_POSITION(texture0, 0x81);
|
|
|
|
|
-ASSERT_REG_POSITION(texture0_format, 0x8e);
|
|
|
|
|
-ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f);
|
|
|
|
|
-ASSERT_REG_POSITION(texture1, 0x91);
|
|
|
|
|
-ASSERT_REG_POSITION(texture1_format, 0x96);
|
|
|
|
|
-ASSERT_REG_POSITION(texture2, 0x99);
|
|
|
|
|
-ASSERT_REG_POSITION(texture2_format, 0x9e);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_stage0, 0xc0);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_stage1, 0xc8);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_stage2, 0xd0);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_stage3, 0xd8);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0);
|
|
|
|
|
-ASSERT_REG_POSITION(fog_mode, 0xe0);
|
|
|
|
|
-ASSERT_REG_POSITION(fog_color, 0xe1);
|
|
|
|
|
-ASSERT_REG_POSITION(fog_lut_offset, 0xe6);
|
|
|
|
|
-ASSERT_REG_POSITION(fog_lut_data, 0xe8);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_stage4, 0xf0);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_stage5, 0xf8);
|
|
|
|
|
-ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd);
|
|
|
|
|
|
|
+ASSERT_REG_POSITION(texturing, 0x80);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture0_enable, 0x80);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture0, 0x81);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture0_format, 0x8e);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture1, 0x91);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture1_format, 0x96);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture2, 0x99);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.texture2_format, 0x9e);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.fog_mode, 0xe0);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.fog_color, 0xe1);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_stage5, 0xf8);
|
|
|
|
|
+ASSERT_REG_POSITION(texturing.tev_combiner_buffer_color, 0xfd);
|
|
|
|
|
+
|
|
|
ASSERT_REG_POSITION(output_merger, 0x100);
|
|
ASSERT_REG_POSITION(output_merger, 0x100);
|
|
|
ASSERT_REG_POSITION(framebuffer, 0x110);
|
|
ASSERT_REG_POSITION(framebuffer, 0x110);
|
|
|
ASSERT_REG_POSITION(lighting, 0x140);
|
|
ASSERT_REG_POSITION(lighting, 0x140);
|