citra/src/video_core/regs_texturing.h
2017-02-04 13:59:09 -08:00

328 lines
8.8 KiB
C++

// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include "common/assert.h"
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
namespace Pica {
struct TexturingRegs {
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;
PAddr GetPhysicalAddress() const {
return address * 8;
}
// 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
};
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:
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<TevStageConfig, 6> GetTevStages() const {
return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}};
};
};
static_assert(sizeof(TexturingRegs) == 0x80 * sizeof(u32),
"TexturingRegs struct has incorrect size");
} // namespace Pica