mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	VideoCore: Split texturing regs from Regs struct
This commit is contained in:
		
							parent
							
								
									000e78144c
								
							
						
					
					
						commit
						9017093f58
					
				@ -123,15 +123,16 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&
 | 
				
			|||||||
void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
 | 
					void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
 | 
				
			||||||
    const unsigned int command_id =
 | 
					    const unsigned int command_id =
 | 
				
			||||||
        list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
 | 
					        list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
 | 
				
			||||||
    if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) ||
 | 
					    if (COMMAND_IN_RANGE(command_id, texturing.texture0) ||
 | 
				
			||||||
        COMMAND_IN_RANGE(command_id, texture2)) {
 | 
					        COMMAND_IN_RANGE(command_id, texturing.texture1) ||
 | 
				
			||||||
 | 
					        COMMAND_IN_RANGE(command_id, texturing.texture2)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned texture_index;
 | 
					        unsigned texture_index;
 | 
				
			||||||
        if (COMMAND_IN_RANGE(command_id, texture0)) {
 | 
					        if (COMMAND_IN_RANGE(command_id, texturing.texture0)) {
 | 
				
			||||||
            texture_index = 0;
 | 
					            texture_index = 0;
 | 
				
			||||||
        } else if (COMMAND_IN_RANGE(command_id, texture1)) {
 | 
					        } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) {
 | 
				
			||||||
            texture_index = 1;
 | 
					            texture_index = 1;
 | 
				
			||||||
        } else if (COMMAND_IN_RANGE(command_id, texture2)) {
 | 
					        } else if (COMMAND_IN_RANGE(command_id, texturing.texture2)) {
 | 
				
			||||||
            texture_index = 2;
 | 
					            texture_index = 2;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            UNREACHABLE_MSG("Unknown texture command");
 | 
					            UNREACHABLE_MSG("Unknown texture command");
 | 
				
			||||||
@ -146,19 +147,20 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const unsigned int command_id =
 | 
					    const unsigned int command_id =
 | 
				
			||||||
        list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
 | 
					        list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
 | 
				
			||||||
    if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) ||
 | 
					    if (COMMAND_IN_RANGE(command_id, texturing.texture0) ||
 | 
				
			||||||
        COMMAND_IN_RANGE(command_id, texture2)) {
 | 
					        COMMAND_IN_RANGE(command_id, texturing.texture1) ||
 | 
				
			||||||
 | 
					        COMMAND_IN_RANGE(command_id, texturing.texture2)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsigned texture_index;
 | 
					        unsigned texture_index;
 | 
				
			||||||
        if (COMMAND_IN_RANGE(command_id, texture0)) {
 | 
					        if (COMMAND_IN_RANGE(command_id, texturing.texture0)) {
 | 
				
			||||||
            texture_index = 0;
 | 
					            texture_index = 0;
 | 
				
			||||||
        } else if (COMMAND_IN_RANGE(command_id, texture1)) {
 | 
					        } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) {
 | 
				
			||||||
            texture_index = 1;
 | 
					            texture_index = 1;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            texture_index = 2;
 | 
					            texture_index = 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto texture = Pica::g_state.regs.GetTextures()[texture_index];
 | 
					        const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index];
 | 
				
			||||||
        const auto config = texture.config;
 | 
					        const auto config = texture.config;
 | 
				
			||||||
        const auto format = texture.format;
 | 
					        const auto format = texture.format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -512,7 +512,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto texture = Pica::g_state.regs.GetTextures()[texture_index];
 | 
					        const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index];
 | 
				
			||||||
        auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format);
 | 
					        auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        surface_address = info.physical_address;
 | 
					        surface_address = info.physical_address;
 | 
				
			||||||
@ -574,7 +574,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
 | 
				
			|||||||
        info.physical_address = surface_address;
 | 
					        info.physical_address = surface_address;
 | 
				
			||||||
        info.width = surface_width;
 | 
					        info.width = surface_width;
 | 
				
			||||||
        info.height = surface_height;
 | 
					        info.height = surface_height;
 | 
				
			||||||
        info.format = static_cast<Pica::Regs::TextureFormat>(surface_format);
 | 
					        info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface_format);
 | 
				
			||||||
        info.SetDefaultStride();
 | 
					        info.SetDefaultStride();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (unsigned int y = 0; y < surface_height; ++y) {
 | 
					        for (unsigned int y = 0; y < surface_height; ++y) {
 | 
				
			||||||
@ -689,7 +689,8 @@ void GraphicsSurfaceWidget::SaveSurface() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) {
 | 
					unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) {
 | 
				
			||||||
    if (format <= Format::MaxTextureFormat) {
 | 
					    if (format <= Format::MaxTextureFormat) {
 | 
				
			||||||
        return Pica::Regs::NibblesPerPixel(static_cast<Pica::Regs::TextureFormat>(format));
 | 
					        return Pica::TexturingRegs::NibblesPerPixel(
 | 
				
			||||||
 | 
					            static_cast<Pica::TexturingRegs::TextureFormat>(format));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (format) {
 | 
					    switch (format) {
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ set(HEADERS
 | 
				
			|||||||
            rasterizer.h
 | 
					            rasterizer.h
 | 
				
			||||||
            rasterizer_interface.h
 | 
					            rasterizer_interface.h
 | 
				
			||||||
            regs_rasterizer.h
 | 
					            regs_rasterizer.h
 | 
				
			||||||
 | 
					            regs_texturing.h
 | 
				
			||||||
            renderer_base.h
 | 
					            renderer_base.h
 | 
				
			||||||
            renderer_opengl/gl_rasterizer.h
 | 
					            renderer_opengl/gl_rasterizer.h
 | 
				
			||||||
            renderer_opengl/gl_rasterizer_cache.h
 | 
					            renderer_opengl/gl_rasterizer_cache.h
 | 
				
			||||||
 | 
				
			|||||||
@ -225,13 +225,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (g_debug_context && g_debug_context->recorder) {
 | 
					        if (g_debug_context && g_debug_context->recorder) {
 | 
				
			||||||
            for (int i = 0; i < 3; ++i) {
 | 
					            for (int i = 0; i < 3; ++i) {
 | 
				
			||||||
                const auto texture = regs.GetTextures()[i];
 | 
					                const auto texture = regs.texturing.GetTextures()[i];
 | 
				
			||||||
                if (!texture.enabled)
 | 
					                if (!texture.enabled)
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
 | 
					                u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
 | 
				
			||||||
                g_debug_context->recorder->MemoryAccessed(
 | 
					                g_debug_context->recorder->MemoryAccessed(
 | 
				
			||||||
                    texture_data, Pica::Regs::NibblesPerPixel(texture.format) *
 | 
					                    texture_data, Pica::TexturingRegs::NibblesPerPixel(texture.format) *
 | 
				
			||||||
                                      texture.config.width / 2 * texture.config.height,
 | 
					                                      texture.config.width / 2 * texture.config.height,
 | 
				
			||||||
                    texture.config.GetPhysicalAddress());
 | 
					                    texture.config.GetPhysicalAddress());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -438,16 +438,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): {
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef): {
 | 
				
			||||||
        g_state.fog.lut[regs.fog_lut_offset % 128].raw = value;
 | 
					        g_state.fog.lut[regs.texturing.fog_lut_offset % 128].raw = value;
 | 
				
			||||||
        regs.fog_lut_offset.Assign(regs.fog_lut_offset + 1);
 | 
					        regs.texturing.fog_lut_offset.Assign(regs.texturing.fog_lut_offset + 1);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -331,7 +331,7 @@ static void FlushIOFile(png_structp png_ptr) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
 | 
					void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data) {
 | 
				
			||||||
#ifndef HAVE_PNG
 | 
					#ifndef HAVE_PNG
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
@ -396,7 +396,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
 | 
				
			|||||||
            info.width = texture_config.width;
 | 
					            info.width = texture_config.width;
 | 
				
			||||||
            info.height = texture_config.height;
 | 
					            info.height = texture_config.height;
 | 
				
			||||||
            info.stride = row_stride;
 | 
					            info.stride = row_stride;
 | 
				
			||||||
            info.format = g_state.regs.texture0_format;
 | 
					            info.format = g_state.regs.texturing.texture0_format;
 | 
				
			||||||
            Math::Vec4<u8> texture_color = Pica::Texture::LookupTexture(data, x, y, info);
 | 
					            Math::Vec4<u8> texture_color = Pica::Texture::LookupTexture(data, x, y, info);
 | 
				
			||||||
            buf[3 * x + y * row_stride] = texture_color.r();
 | 
					            buf[3 * x + y * row_stride] = texture_color.r();
 | 
				
			||||||
            buf[3 * x + y * row_stride + 1] = texture_color.g();
 | 
					            buf[3 * x + y * row_stride + 1] = texture_color.g();
 | 
				
			||||||
@ -434,8 +434,10 @@ static std::string ReplacePattern(const std::string& input, const std::string& p
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfig::Source& source) {
 | 
					static std::string GetTevStageConfigSourceString(
 | 
				
			||||||
    using Source = Pica::Regs::TevStageConfig::Source;
 | 
					    const TexturingRegs::TevStageConfig::Source& source) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using Source = TexturingRegs::TevStageConfig::Source;
 | 
				
			||||||
    static const std::map<Source, std::string> source_map = {
 | 
					    static const std::map<Source, std::string> source_map = {
 | 
				
			||||||
        {Source::PrimaryColor, "PrimaryColor"},
 | 
					        {Source::PrimaryColor, "PrimaryColor"},
 | 
				
			||||||
        {Source::PrimaryFragmentColor, "PrimaryFragmentColor"},
 | 
					        {Source::PrimaryFragmentColor, "PrimaryFragmentColor"},
 | 
				
			||||||
@ -457,9 +459,10 @@ static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfi
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::string GetTevStageConfigColorSourceString(
 | 
					static std::string GetTevStageConfigColorSourceString(
 | 
				
			||||||
    const Pica::Regs::TevStageConfig::Source& source,
 | 
					    const TexturingRegs::TevStageConfig::Source& source,
 | 
				
			||||||
    const Pica::Regs::TevStageConfig::ColorModifier modifier) {
 | 
					    const TexturingRegs::TevStageConfig::ColorModifier modifier) {
 | 
				
			||||||
    using ColorModifier = Pica::Regs::TevStageConfig::ColorModifier;
 | 
					
 | 
				
			||||||
 | 
					    using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier;
 | 
				
			||||||
    static const std::map<ColorModifier, std::string> color_modifier_map = {
 | 
					    static const std::map<ColorModifier, std::string> color_modifier_map = {
 | 
				
			||||||
        {ColorModifier::SourceColor, "%source.rgb"},
 | 
					        {ColorModifier::SourceColor, "%source.rgb"},
 | 
				
			||||||
        {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"},
 | 
					        {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"},
 | 
				
			||||||
@ -483,9 +486,10 @@ static std::string GetTevStageConfigColorSourceString(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::string GetTevStageConfigAlphaSourceString(
 | 
					static std::string GetTevStageConfigAlphaSourceString(
 | 
				
			||||||
    const Pica::Regs::TevStageConfig::Source& source,
 | 
					    const TexturingRegs::TevStageConfig::Source& source,
 | 
				
			||||||
    const Pica::Regs::TevStageConfig::AlphaModifier modifier) {
 | 
					    const TexturingRegs::TevStageConfig::AlphaModifier modifier) {
 | 
				
			||||||
    using AlphaModifier = Pica::Regs::TevStageConfig::AlphaModifier;
 | 
					
 | 
				
			||||||
 | 
					    using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier;
 | 
				
			||||||
    static const std::map<AlphaModifier, std::string> alpha_modifier_map = {
 | 
					    static const std::map<AlphaModifier, std::string> alpha_modifier_map = {
 | 
				
			||||||
        {AlphaModifier::SourceAlpha, "%source.a"},
 | 
					        {AlphaModifier::SourceAlpha, "%source.a"},
 | 
				
			||||||
        {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"},
 | 
					        {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"},
 | 
				
			||||||
@ -507,8 +511,9 @@ static std::string GetTevStageConfigAlphaSourceString(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::string GetTevStageConfigOperationString(
 | 
					static std::string GetTevStageConfigOperationString(
 | 
				
			||||||
    const Pica::Regs::TevStageConfig::Operation& operation) {
 | 
					    const TexturingRegs::TevStageConfig::Operation& operation) {
 | 
				
			||||||
    using Operation = Pica::Regs::TevStageConfig::Operation;
 | 
					
 | 
				
			||||||
 | 
					    using Operation = TexturingRegs::TevStageConfig::Operation;
 | 
				
			||||||
    static const std::map<Operation, std::string> combiner_map = {
 | 
					    static const std::map<Operation, std::string> combiner_map = {
 | 
				
			||||||
        {Operation::Replace, "%source1"},
 | 
					        {Operation::Replace, "%source1"},
 | 
				
			||||||
        {Operation::Modulate, "(%source1 * %source2)"},
 | 
					        {Operation::Modulate, "(%source1 * %source2)"},
 | 
				
			||||||
@ -528,7 +533,7 @@ static std::string GetTevStageConfigOperationString(
 | 
				
			|||||||
    return op_it->second;
 | 
					    return op_it->second;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage) {
 | 
					std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage) {
 | 
				
			||||||
    auto op_str = GetTevStageConfigOperationString(tev_stage.color_op);
 | 
					    auto op_str = GetTevStageConfigOperationString(tev_stage.color_op);
 | 
				
			||||||
    op_str = ReplacePattern(
 | 
					    op_str = ReplacePattern(
 | 
				
			||||||
        op_str, "%source1",
 | 
					        op_str, "%source1",
 | 
				
			||||||
@ -541,7 +546,7 @@ std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfi
 | 
				
			|||||||
        GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3));
 | 
					        GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage) {
 | 
					std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage) {
 | 
				
			||||||
    auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op);
 | 
					    auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op);
 | 
				
			||||||
    op_str = ReplacePattern(
 | 
					    op_str = ReplacePattern(
 | 
				
			||||||
        op_str, "%source1",
 | 
					        op_str, "%source1",
 | 
				
			||||||
@ -554,7 +559,7 @@ std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfi
 | 
				
			|||||||
        GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3));
 | 
					        GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig, 6>& stages) {
 | 
					void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages) {
 | 
				
			||||||
    std::string stage_info = "Tev setup:\n";
 | 
					    std::string stage_info = "Tev setup:\n";
 | 
				
			||||||
    for (size_t index = 0; index < stages.size(); ++index) {
 | 
					    for (size_t index = 0; index < stages.size(); ++index) {
 | 
				
			||||||
        const auto& tev_stage = stages[index];
 | 
					        const auto& tev_stage = stages[index];
 | 
				
			||||||
 | 
				
			|||||||
@ -205,13 +205,13 @@ inline bool IsPicaTracing() {
 | 
				
			|||||||
void OnPicaRegWrite(PicaTrace::Write write);
 | 
					void OnPicaRegWrite(PicaTrace::Write write);
 | 
				
			||||||
std::unique_ptr<PicaTrace> FinishPicaTracing();
 | 
					std::unique_ptr<PicaTrace> FinishPicaTracing();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data);
 | 
					void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage);
 | 
					std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage);
 | 
				
			||||||
std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage);
 | 
					std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Dumps the Tev stage config to log at trace level
 | 
					/// Dumps the Tev stage config to log at trace level
 | 
				
			||||||
void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig, 6>& stages);
 | 
					void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Used in the vertex loader to merge access records. TODO: Investigate if actually useful.
 | 
					 * Used in the vertex loader to merge access records. TODO: Investigate if actually useful.
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
					    TexturingRegs texturing;
 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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(texturing, 0x80);
 | 
				
			||||||
ASSERT_REG_POSITION(texture0, 0x81);
 | 
					ASSERT_REG_POSITION(texturing.texture0_enable, 0x80);
 | 
				
			||||||
ASSERT_REG_POSITION(texture0_format, 0x8e);
 | 
					ASSERT_REG_POSITION(texturing.texture0, 0x81);
 | 
				
			||||||
ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f);
 | 
					ASSERT_REG_POSITION(texturing.texture0_format, 0x8e);
 | 
				
			||||||
ASSERT_REG_POSITION(texture1, 0x91);
 | 
					ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f);
 | 
				
			||||||
ASSERT_REG_POSITION(texture1_format, 0x96);
 | 
					ASSERT_REG_POSITION(texturing.texture1, 0x91);
 | 
				
			||||||
ASSERT_REG_POSITION(texture2, 0x99);
 | 
					ASSERT_REG_POSITION(texturing.texture1_format, 0x96);
 | 
				
			||||||
ASSERT_REG_POSITION(texture2_format, 0x9e);
 | 
					ASSERT_REG_POSITION(texturing.texture2, 0x99);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_stage0, 0xc0);
 | 
					ASSERT_REG_POSITION(texturing.texture2_format, 0x9e);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_stage1, 0xc8);
 | 
					ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_stage2, 0xd0);
 | 
					ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_stage3, 0xd8);
 | 
					ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0);
 | 
					ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8);
 | 
				
			||||||
ASSERT_REG_POSITION(fog_mode, 0xe0);
 | 
					ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0);
 | 
				
			||||||
ASSERT_REG_POSITION(fog_color, 0xe1);
 | 
					ASSERT_REG_POSITION(texturing.fog_mode, 0xe0);
 | 
				
			||||||
ASSERT_REG_POSITION(fog_lut_offset, 0xe6);
 | 
					ASSERT_REG_POSITION(texturing.fog_color, 0xe1);
 | 
				
			||||||
ASSERT_REG_POSITION(fog_lut_data, 0xe8);
 | 
					ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_stage4, 0xf0);
 | 
					ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_stage5, 0xf8);
 | 
					ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0);
 | 
				
			||||||
ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd);
 | 
					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);
 | 
				
			||||||
 | 
				
			|||||||
@ -397,8 +397,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
 | 
					    auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto textures = regs.GetTextures();
 | 
					    auto textures = regs.texturing.GetTextures();
 | 
				
			||||||
    auto tev_stages = regs.GetTevStages();
 | 
					    auto tev_stages = regs.texturing.GetTevStages();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable &&
 | 
					    bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable &&
 | 
				
			||||||
                                 g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8;
 | 
					                                 g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8;
 | 
				
			||||||
@ -515,9 +515,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
                // TODO: Refactor so cubemaps and shadowmaps can be handled
 | 
					                // TODO: Refactor so cubemaps and shadowmaps can be handled
 | 
				
			||||||
                if (i == 0) {
 | 
					                if (i == 0) {
 | 
				
			||||||
                    switch (texture.config.type) {
 | 
					                    switch (texture.config.type) {
 | 
				
			||||||
                    case Regs::TextureConfig::Texture2D:
 | 
					                    case TexturingRegs::TextureConfig::Texture2D:
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case Regs::TextureConfig::Projection2D: {
 | 
					                    case TexturingRegs::TextureConfig::Projection2D: {
 | 
				
			||||||
                        auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w);
 | 
					                        auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w);
 | 
				
			||||||
                        u /= tc0_w;
 | 
					                        u /= tc0_w;
 | 
				
			||||||
                        v /= tc0_w;
 | 
					                        v /= tc0_w;
 | 
				
			||||||
@ -536,21 +536,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
                int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height)))
 | 
					                int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height)))
 | 
				
			||||||
                            .ToFloat32();
 | 
					                            .ToFloat32();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val,
 | 
					                static auto GetWrappedTexCoord = [](TexturingRegs::TextureConfig::WrapMode mode,
 | 
				
			||||||
                                                    unsigned size) {
 | 
					                                                    int val, unsigned size) {
 | 
				
			||||||
                    switch (mode) {
 | 
					                    switch (mode) {
 | 
				
			||||||
                    case Regs::TextureConfig::ClampToEdge:
 | 
					                    case TexturingRegs::TextureConfig::ClampToEdge:
 | 
				
			||||||
                        val = std::max(val, 0);
 | 
					                        val = std::max(val, 0);
 | 
				
			||||||
                        val = std::min(val, (int)size - 1);
 | 
					                        val = std::min(val, (int)size - 1);
 | 
				
			||||||
                        return val;
 | 
					                        return val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case Regs::TextureConfig::ClampToBorder:
 | 
					                    case TexturingRegs::TextureConfig::ClampToBorder:
 | 
				
			||||||
                        return val;
 | 
					                        return val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case Regs::TextureConfig::Repeat:
 | 
					                    case TexturingRegs::TextureConfig::Repeat:
 | 
				
			||||||
                        return (int)((unsigned)val % size);
 | 
					                        return (int)((unsigned)val % size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case Regs::TextureConfig::MirroredRepeat: {
 | 
					                    case TexturingRegs::TextureConfig::MirroredRepeat: {
 | 
				
			||||||
                        unsigned int coord = ((unsigned)val % (2 * size));
 | 
					                        unsigned int coord = ((unsigned)val % (2 * size));
 | 
				
			||||||
                        if (coord >= size)
 | 
					                        if (coord >= size)
 | 
				
			||||||
                            coord = 2 * size - 1 - coord;
 | 
					                            coord = 2 * size - 1 - coord;
 | 
				
			||||||
@ -564,9 +564,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ((texture.config.wrap_s == Regs::TextureConfig::ClampToBorder &&
 | 
					                if ((texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder &&
 | 
				
			||||||
                     (s < 0 || static_cast<u32>(s) >= texture.config.width)) ||
 | 
					                     (s < 0 || static_cast<u32>(s) >= texture.config.width)) ||
 | 
				
			||||||
                    (texture.config.wrap_t == Regs::TextureConfig::ClampToBorder &&
 | 
					                    (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder &&
 | 
				
			||||||
                     (t < 0 || static_cast<u32>(t) >= texture.config.height))) {
 | 
					                     (t < 0 || static_cast<u32>(t) >= texture.config.height))) {
 | 
				
			||||||
                    auto border_color = texture.config.border_color;
 | 
					                    auto border_color = texture.config.border_color;
 | 
				
			||||||
                    texture_color[i] = {border_color.r, border_color.g, border_color.b,
 | 
					                    texture_color[i] = {border_color.r, border_color.g, border_color.b,
 | 
				
			||||||
@ -602,17 +602,19 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
            Math::Vec4<u8> combiner_output;
 | 
					            Math::Vec4<u8> combiner_output;
 | 
				
			||||||
            Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0};
 | 
					            Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0};
 | 
				
			||||||
            Math::Vec4<u8> next_combiner_buffer = {
 | 
					            Math::Vec4<u8> next_combiner_buffer = {
 | 
				
			||||||
                regs.tev_combiner_buffer_color.r, regs.tev_combiner_buffer_color.g,
 | 
					                regs.texturing.tev_combiner_buffer_color.r,
 | 
				
			||||||
                regs.tev_combiner_buffer_color.b, regs.tev_combiner_buffer_color.a,
 | 
					                regs.texturing.tev_combiner_buffer_color.g,
 | 
				
			||||||
 | 
					                regs.texturing.tev_combiner_buffer_color.b,
 | 
				
			||||||
 | 
					                regs.texturing.tev_combiner_buffer_color.a,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size();
 | 
					            for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size();
 | 
				
			||||||
                 ++tev_stage_index) {
 | 
					                 ++tev_stage_index) {
 | 
				
			||||||
                const auto& tev_stage = tev_stages[tev_stage_index];
 | 
					                const auto& tev_stage = tev_stages[tev_stage_index];
 | 
				
			||||||
                using Source = Regs::TevStageConfig::Source;
 | 
					                using Source = TexturingRegs::TevStageConfig::Source;
 | 
				
			||||||
                using ColorModifier = Regs::TevStageConfig::ColorModifier;
 | 
					                using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier;
 | 
				
			||||||
                using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
 | 
					                using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier;
 | 
				
			||||||
                using Operation = Regs::TevStageConfig::Operation;
 | 
					                using Operation = TexturingRegs::TevStageConfig::Operation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                auto GetSource = [&](Source source) -> Math::Vec4<u8> {
 | 
					                auto GetSource = [&](Source source) -> Math::Vec4<u8> {
 | 
				
			||||||
                    switch (source) {
 | 
					                    switch (source) {
 | 
				
			||||||
@ -864,14 +866,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                combiner_buffer = next_combiner_buffer;
 | 
					                combiner_buffer = next_combiner_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(
 | 
					                if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(
 | 
				
			||||||
                        tev_stage_index)) {
 | 
					                        tev_stage_index)) {
 | 
				
			||||||
                    next_combiner_buffer.r() = combiner_output.r();
 | 
					                    next_combiner_buffer.r() = combiner_output.r();
 | 
				
			||||||
                    next_combiner_buffer.g() = combiner_output.g();
 | 
					                    next_combiner_buffer.g() = combiner_output.g();
 | 
				
			||||||
                    next_combiner_buffer.b() = combiner_output.b();
 | 
					                    next_combiner_buffer.b() = combiner_output.b();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(
 | 
					                if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(
 | 
				
			||||||
                        tev_stage_index)) {
 | 
					                        tev_stage_index)) {
 | 
				
			||||||
                    next_combiner_buffer.a() = combiner_output.a();
 | 
					                    next_combiner_buffer.a() = combiner_output.a();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -924,16 +926,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
 | 
				
			|||||||
            // Not fully accurate. We'd have to know what data type is used to
 | 
					            // Not fully accurate. We'd have to know what data type is used to
 | 
				
			||||||
            // 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.fog_mode == Regs::FogMode::Fog) {
 | 
					            if (regs.texturing.fog_mode == TexturingRegs::FogMode::Fog) {
 | 
				
			||||||
                const Math::Vec3<u8> fog_color = {
 | 
					                const Math::Vec3<u8> fog_color = {
 | 
				
			||||||
                    static_cast<u8>(regs.fog_color.r.Value()),
 | 
					                    static_cast<u8>(regs.texturing.fog_color.r.Value()),
 | 
				
			||||||
                    static_cast<u8>(regs.fog_color.g.Value()),
 | 
					                    static_cast<u8>(regs.texturing.fog_color.g.Value()),
 | 
				
			||||||
                    static_cast<u8>(regs.fog_color.b.Value()),
 | 
					                    static_cast<u8>(regs.texturing.fog_color.b.Value()),
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Get index into fog LUT
 | 
					                // Get index into fog LUT
 | 
				
			||||||
                float fog_index;
 | 
					                float fog_index;
 | 
				
			||||||
                if (g_state.regs.fog_flip) {
 | 
					                if (g_state.regs.texturing.fog_flip) {
 | 
				
			||||||
                    fog_index = (1.0f - depth) * 128.0f;
 | 
					                    fog_index = (1.0f - depth) * 128.0f;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    fog_index = depth * 128.0f;
 | 
					                    fog_index = depth * 128.0f;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										328
									
								
								src/video_core/regs_texturing.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								src/video_core/regs_texturing.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,328 @@
 | 
				
			|||||||
 | 
					// 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
 | 
				
			||||||
@ -26,13 +26,15 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
 | 
				
			|||||||
MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
 | 
					MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
 | 
				
			||||||
MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
 | 
					MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) {
 | 
					static bool IsPassThroughTevStage(const Pica::TexturingRegs::TevStageConfig& stage) {
 | 
				
			||||||
    return (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace &&
 | 
					    using TevStageConfig = Pica::TexturingRegs::TevStageConfig;
 | 
				
			||||||
            stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace &&
 | 
					
 | 
				
			||||||
            stage.color_source1 == Pica::Regs::TevStageConfig::Source::Previous &&
 | 
					    return (stage.color_op == TevStageConfig::Operation::Replace &&
 | 
				
			||||||
            stage.alpha_source1 == Pica::Regs::TevStageConfig::Source::Previous &&
 | 
					            stage.alpha_op == TevStageConfig::Operation::Replace &&
 | 
				
			||||||
            stage.color_modifier1 == Pica::Regs::TevStageConfig::ColorModifier::SourceColor &&
 | 
					            stage.color_source1 == TevStageConfig::Source::Previous &&
 | 
				
			||||||
            stage.alpha_modifier1 == Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha &&
 | 
					            stage.alpha_source1 == TevStageConfig::Source::Previous &&
 | 
				
			||||||
 | 
					            stage.color_modifier1 == TevStageConfig::ColorModifier::SourceColor &&
 | 
				
			||||||
 | 
					            stage.alpha_modifier1 == TevStageConfig::AlphaModifier::SourceAlpha &&
 | 
				
			||||||
            stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1);
 | 
					            stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -242,7 +244,7 @@ void RasterizerOpenGL::DrawTriangles() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Sync and bind the texture surfaces
 | 
					    // Sync and bind the texture surfaces
 | 
				
			||||||
    const auto pica_textures = regs.GetTextures();
 | 
					    const auto pica_textures = regs.texturing.GetTextures();
 | 
				
			||||||
    for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
 | 
					    for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
 | 
				
			||||||
        const auto& texture = pica_textures[texture_index];
 | 
					        const auto& texture = pica_textures[texture_index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -348,17 +350,17 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Fog state
 | 
					    // Fog state
 | 
				
			||||||
    case PICA_REG_INDEX(fog_color):
 | 
					    case PICA_REG_INDEX(texturing.fog_color):
 | 
				
			||||||
        SyncFogColor();
 | 
					        SyncFogColor();
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee):
 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef):
 | 
					    case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef):
 | 
				
			||||||
        uniform_block_data.fog_lut_dirty = true;
 | 
					        uniform_block_data.fog_lut_dirty = true;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -411,60 +413,60 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Texture 0 type
 | 
					    // Texture 0 type
 | 
				
			||||||
    case PICA_REG_INDEX(texture0.type):
 | 
					    case PICA_REG_INDEX(texturing.texture0.type):
 | 
				
			||||||
        shader_dirty = true;
 | 
					        shader_dirty = true;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TEV stages
 | 
					    // TEV stages
 | 
				
			||||||
    // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input)
 | 
					    // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input)
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage0.color_source1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage0.color_source1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage0.color_modifier1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage0.color_modifier1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage0.color_op):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage0.color_op):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage0.color_scale):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage0.color_scale):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage1.color_source1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage1.color_source1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage1.color_modifier1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage1.color_modifier1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage1.color_op):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage1.color_op):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage1.color_scale):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage1.color_scale):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage2.color_source1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage2.color_source1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage2.color_modifier1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage2.color_modifier1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage2.color_op):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage2.color_op):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage2.color_scale):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage2.color_scale):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage3.color_source1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage3.color_source1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage3.color_modifier1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage3.color_modifier1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage3.color_op):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage3.color_op):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage3.color_scale):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage3.color_scale):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage4.color_source1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage4.color_source1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage4.color_modifier1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage4.color_modifier1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage4.color_op):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage4.color_op):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage4.color_scale):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage4.color_scale):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage5.color_source1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage5.color_source1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage5.color_modifier1):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage5.color_modifier1):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage5.color_op):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage5.color_op):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage5.color_scale):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage5.color_scale):
 | 
				
			||||||
    case PICA_REG_INDEX(tev_combiner_buffer_input):
 | 
					    case PICA_REG_INDEX(texturing.tev_combiner_buffer_input):
 | 
				
			||||||
        shader_dirty = true;
 | 
					        shader_dirty = true;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage0.const_r):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage0.const_r):
 | 
				
			||||||
        SyncTevConstColor(0, regs.tev_stage0);
 | 
					        SyncTevConstColor(0, regs.texturing.tev_stage0);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage1.const_r):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage1.const_r):
 | 
				
			||||||
        SyncTevConstColor(1, regs.tev_stage1);
 | 
					        SyncTevConstColor(1, regs.texturing.tev_stage1);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage2.const_r):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage2.const_r):
 | 
				
			||||||
        SyncTevConstColor(2, regs.tev_stage2);
 | 
					        SyncTevConstColor(2, regs.texturing.tev_stage2);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage3.const_r):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage3.const_r):
 | 
				
			||||||
        SyncTevConstColor(3, regs.tev_stage3);
 | 
					        SyncTevConstColor(3, regs.texturing.tev_stage3);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage4.const_r):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage4.const_r):
 | 
				
			||||||
        SyncTevConstColor(4, regs.tev_stage4);
 | 
					        SyncTevConstColor(4, regs.texturing.tev_stage4);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PICA_REG_INDEX(tev_stage5.const_r):
 | 
					    case PICA_REG_INDEX(texturing.tev_stage5.const_r):
 | 
				
			||||||
        SyncTevConstColor(5, regs.tev_stage5);
 | 
					        SyncTevConstColor(5, regs.texturing.tev_stage5);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TEV combiner buffer color
 | 
					    // TEV combiner buffer color
 | 
				
			||||||
    case PICA_REG_INDEX(tev_combiner_buffer_color):
 | 
					    case PICA_REG_INDEX(texturing.tev_combiner_buffer_color):
 | 
				
			||||||
        SyncCombinerColor();
 | 
					        SyncCombinerColor();
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -979,7 +981,9 @@ void RasterizerOpenGL::SamplerInfo::Create() {
 | 
				
			|||||||
    // Other attributes have correct defaults
 | 
					    // Other attributes have correct defaults
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Pica::Regs::TextureConfig& config) {
 | 
					void RasterizerOpenGL::SamplerInfo::SyncWithConfig(
 | 
				
			||||||
 | 
					    const Pica::TexturingRegs::TextureConfig& config) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GLuint s = sampler.handle;
 | 
					    GLuint s = sampler.handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (mag_filter != config.mag_filter) {
 | 
					    if (mag_filter != config.mag_filter) {
 | 
				
			||||||
@ -1091,7 +1095,7 @@ void RasterizerOpenGL::SetShader() {
 | 
				
			|||||||
        SyncDepthOffset();
 | 
					        SyncDepthOffset();
 | 
				
			||||||
        SyncAlphaTest();
 | 
					        SyncAlphaTest();
 | 
				
			||||||
        SyncCombinerColor();
 | 
					        SyncCombinerColor();
 | 
				
			||||||
        auto& tev_stages = Pica::g_state.regs.GetTevStages();
 | 
					        auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages();
 | 
				
			||||||
        for (int index = 0; index < tev_stages.size(); ++index)
 | 
					        for (int index = 0; index < tev_stages.size(); ++index)
 | 
				
			||||||
            SyncTevConstColor(index, tev_stages[index]);
 | 
					            SyncTevConstColor(index, tev_stages[index]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1182,8 +1186,8 @@ void RasterizerOpenGL::SyncBlendColor() {
 | 
				
			|||||||
void RasterizerOpenGL::SyncFogColor() {
 | 
					void RasterizerOpenGL::SyncFogColor() {
 | 
				
			||||||
    const auto& regs = Pica::g_state.regs;
 | 
					    const auto& regs = Pica::g_state.regs;
 | 
				
			||||||
    uniform_block_data.data.fog_color = {
 | 
					    uniform_block_data.data.fog_color = {
 | 
				
			||||||
        regs.fog_color.r.Value() / 255.0f, regs.fog_color.g.Value() / 255.0f,
 | 
					        regs.texturing.fog_color.r.Value() / 255.0f, regs.texturing.fog_color.g.Value() / 255.0f,
 | 
				
			||||||
        regs.fog_color.b.Value() / 255.0f,
 | 
					        regs.texturing.fog_color.b.Value() / 255.0f,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    uniform_block_data.dirty = true;
 | 
					    uniform_block_data.dirty = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1267,7 +1271,8 @@ void RasterizerOpenGL::SyncDepthTest() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::SyncCombinerColor() {
 | 
					void RasterizerOpenGL::SyncCombinerColor() {
 | 
				
			||||||
    auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw);
 | 
					    auto combiner_color =
 | 
				
			||||||
 | 
					        PicaToGL::ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw);
 | 
				
			||||||
    if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
 | 
					    if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
 | 
				
			||||||
        uniform_block_data.data.tev_combiner_buffer_color = combiner_color;
 | 
					        uniform_block_data.data.tev_combiner_buffer_color = combiner_color;
 | 
				
			||||||
        uniform_block_data.dirty = true;
 | 
					        uniform_block_data.dirty = true;
 | 
				
			||||||
@ -1275,7 +1280,7 @@ void RasterizerOpenGL::SyncCombinerColor() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::SyncTevConstColor(int stage_index,
 | 
					void RasterizerOpenGL::SyncTevConstColor(int stage_index,
 | 
				
			||||||
                                         const Pica::Regs::TevStageConfig& tev_stage) {
 | 
					                                         const Pica::TexturingRegs::TevStageConfig& tev_stage) {
 | 
				
			||||||
    auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color);
 | 
					    auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color);
 | 
				
			||||||
    if (const_color != uniform_block_data.data.const_color[stage_index]) {
 | 
					    if (const_color != uniform_block_data.data.const_color[stage_index]) {
 | 
				
			||||||
        uniform_block_data.data.const_color[stage_index] = const_color;
 | 
					        uniform_block_data.data.const_color[stage_index] = const_color;
 | 
				
			||||||
 | 
				
			|||||||
@ -60,12 +60,12 @@ union PicaShaderConfig {
 | 
				
			|||||||
                                    ? regs.output_merger.alpha_test.func.Value()
 | 
					                                    ? regs.output_merger.alpha_test.func.Value()
 | 
				
			||||||
                                    : Pica::Regs::CompareFunc::Always;
 | 
					                                    : Pica::Regs::CompareFunc::Always;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        state.texture0_type = regs.texture0.type;
 | 
					        state.texture0_type = regs.texturing.texture0.type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Copy relevant tev stages fields.
 | 
					        // Copy relevant tev stages fields.
 | 
				
			||||||
        // We don't sync const_color here because of the high variance, it is a
 | 
					        // We don't sync const_color here because of the high variance, it is a
 | 
				
			||||||
        // shader uniform instead.
 | 
					        // shader uniform instead.
 | 
				
			||||||
        const auto& tev_stages = regs.GetTevStages();
 | 
					        const auto& tev_stages = regs.texturing.GetTevStages();
 | 
				
			||||||
        DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size());
 | 
					        DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size());
 | 
				
			||||||
        for (size_t i = 0; i < tev_stages.size(); i++) {
 | 
					        for (size_t i = 0; i < tev_stages.size(); i++) {
 | 
				
			||||||
            const auto& tev_stage = tev_stages[i];
 | 
					            const auto& tev_stage = tev_stages[i];
 | 
				
			||||||
@ -75,11 +75,12 @@ union PicaShaderConfig {
 | 
				
			|||||||
            state.tev_stages[i].scales_raw = tev_stage.scales_raw;
 | 
					            state.tev_stages[i].scales_raw = tev_stage.scales_raw;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        state.fog_mode = regs.fog_mode;
 | 
					        state.fog_mode = regs.texturing.fog_mode;
 | 
				
			||||||
        state.fog_flip = regs.fog_flip != 0;
 | 
					        state.fog_flip = regs.texturing.fog_flip != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        state.combiner_buffer_input = regs.tev_combiner_buffer_input.update_mask_rgb.Value() |
 | 
					        state.combiner_buffer_input =
 | 
				
			||||||
                                      regs.tev_combiner_buffer_input.update_mask_a.Value() << 4;
 | 
					            regs.texturing.tev_combiner_buffer_input.update_mask_rgb.Value() |
 | 
				
			||||||
 | 
					            regs.texturing.tev_combiner_buffer_input.update_mask_a.Value() << 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Fragment lighting
 | 
					        // Fragment lighting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -159,8 +160,8 @@ union PicaShaderConfig {
 | 
				
			|||||||
        u32 modifiers_raw;
 | 
					        u32 modifiers_raw;
 | 
				
			||||||
        u32 ops_raw;
 | 
					        u32 ops_raw;
 | 
				
			||||||
        u32 scales_raw;
 | 
					        u32 scales_raw;
 | 
				
			||||||
        explicit operator Pica::Regs::TevStageConfig() const noexcept {
 | 
					        explicit operator Pica::TexturingRegs::TevStageConfig() const noexcept {
 | 
				
			||||||
            Pica::Regs::TevStageConfig stage;
 | 
					            Pica::TexturingRegs::TevStageConfig stage;
 | 
				
			||||||
            stage.sources_raw = sources_raw;
 | 
					            stage.sources_raw = sources_raw;
 | 
				
			||||||
            stage.modifiers_raw = modifiers_raw;
 | 
					            stage.modifiers_raw = modifiers_raw;
 | 
				
			||||||
            stage.ops_raw = ops_raw;
 | 
					            stage.ops_raw = ops_raw;
 | 
				
			||||||
@ -173,12 +174,12 @@ union PicaShaderConfig {
 | 
				
			|||||||
    struct State {
 | 
					    struct State {
 | 
				
			||||||
        Pica::Regs::CompareFunc alpha_test_func;
 | 
					        Pica::Regs::CompareFunc alpha_test_func;
 | 
				
			||||||
        Pica::RasterizerRegs::ScissorMode scissor_test_mode;
 | 
					        Pica::RasterizerRegs::ScissorMode scissor_test_mode;
 | 
				
			||||||
        Pica::Regs::TextureConfig::TextureType texture0_type;
 | 
					        Pica::TexturingRegs::TextureConfig::TextureType texture0_type;
 | 
				
			||||||
        std::array<TevStageConfigRaw, 6> tev_stages;
 | 
					        std::array<TevStageConfigRaw, 6> tev_stages;
 | 
				
			||||||
        u8 combiner_buffer_input;
 | 
					        u8 combiner_buffer_input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Pica::RasterizerRegs::DepthBuffering depthmap_enable;
 | 
					        Pica::RasterizerRegs::DepthBuffering depthmap_enable;
 | 
				
			||||||
        Pica::Regs::FogMode fog_mode;
 | 
					        Pica::TexturingRegs::FogMode fog_mode;
 | 
				
			||||||
        bool fog_flip;
 | 
					        bool fog_flip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct {
 | 
					        struct {
 | 
				
			||||||
@ -251,7 +252,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    struct SamplerInfo {
 | 
					    struct SamplerInfo {
 | 
				
			||||||
        using TextureConfig = Pica::Regs::TextureConfig;
 | 
					        using TextureConfig = Pica::TexturingRegs::TextureConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OGLSampler sampler;
 | 
					        OGLSampler sampler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -398,7 +399,7 @@ private:
 | 
				
			|||||||
    void SyncCombinerColor();
 | 
					    void SyncCombinerColor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Syncs the TEV constant color to match the PICA register
 | 
					    /// Syncs the TEV constant color to match the PICA register
 | 
				
			||||||
    void SyncTevConstColor(int tev_index, const Pica::Regs::TevStageConfig& tev_stage);
 | 
					    void SyncTevConstColor(int tev_index, const Pica::TexturingRegs::TevStageConfig& tev_stage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Syncs the lighting global ambient color to match the PICA register
 | 
					    /// Syncs the lighting global ambient color to match the PICA register
 | 
				
			||||||
    void SyncGlobalAmbient();
 | 
					    void SyncGlobalAmbient();
 | 
				
			||||||
 | 
				
			|||||||
@ -342,7 +342,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo
 | 
				
			|||||||
                Pica::Texture::TextureInfo tex_info;
 | 
					                Pica::Texture::TextureInfo tex_info;
 | 
				
			||||||
                tex_info.width = params.width;
 | 
					                tex_info.width = params.width;
 | 
				
			||||||
                tex_info.height = params.height;
 | 
					                tex_info.height = params.height;
 | 
				
			||||||
                tex_info.format = (Pica::Regs::TextureFormat)params.pixel_format;
 | 
					                tex_info.format = (Pica::TexturingRegs::TextureFormat)params.pixel_format;
 | 
				
			||||||
                tex_info.SetDefaultStride();
 | 
					                tex_info.SetDefaultStride();
 | 
				
			||||||
                tex_info.physical_address = params.addr;
 | 
					                tex_info.physical_address = params.addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -510,7 +510,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CachedSurface* RasterizerCacheOpenGL::GetTextureSurface(
 | 
					CachedSurface* RasterizerCacheOpenGL::GetTextureSurface(
 | 
				
			||||||
    const Pica::Regs::FullTextureConfig& config) {
 | 
					    const Pica::TexturingRegs::FullTextureConfig& config) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Pica::Texture::TextureInfo info =
 | 
					    Pica::Texture::TextureInfo info =
 | 
				
			||||||
        Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format);
 | 
					        Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format);
 | 
				
			||||||
 | 
				
			|||||||
@ -96,7 +96,7 @@ struct CachedSurface {
 | 
				
			|||||||
        return bpp_table[(unsigned int)format];
 | 
					        return bpp_table[(unsigned int)format];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static PixelFormat PixelFormatFromTextureFormat(Pica::Regs::TextureFormat format) {
 | 
					    static PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) {
 | 
				
			||||||
        return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid;
 | 
					        return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -212,7 +212,7 @@ public:
 | 
				
			|||||||
                                  bool load_if_create, MathUtil::Rectangle<int>& out_rect);
 | 
					                                  bool load_if_create, MathUtil::Rectangle<int>& out_rect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Gets a surface based on the texture configuration
 | 
					    /// Gets a surface based on the texture configuration
 | 
				
			||||||
    CachedSurface* GetTextureSurface(const Pica::Regs::FullTextureConfig& config);
 | 
					    CachedSurface* GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer
 | 
					    /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer
 | 
				
			||||||
    /// configuration
 | 
					    /// configuration
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using Pica::Regs;
 | 
					using Pica::Regs;
 | 
				
			||||||
using Pica::RasterizerRegs;
 | 
					using Pica::RasterizerRegs;
 | 
				
			||||||
using TevStageConfig = Regs::TevStageConfig;
 | 
					using TevStageConfig = Pica::TexturingRegs::TevStageConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace GLShader {
 | 
					namespace GLShader {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -47,10 +47,10 @@ static void AppendSource(std::string& out, const PicaShaderConfig& config,
 | 
				
			|||||||
    case Source::Texture0:
 | 
					    case Source::Texture0:
 | 
				
			||||||
        // Only unit 0 respects the texturing type (according to 3DBrew)
 | 
					        // Only unit 0 respects the texturing type (according to 3DBrew)
 | 
				
			||||||
        switch (state.texture0_type) {
 | 
					        switch (state.texture0_type) {
 | 
				
			||||||
        case Pica::Regs::TextureConfig::Texture2D:
 | 
					        case Pica::TexturingRegs::TextureConfig::Texture2D:
 | 
				
			||||||
            out += "texture(tex[0], texcoord[0])";
 | 
					            out += "texture(tex[0], texcoord[0])";
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case Pica::Regs::TextureConfig::Projection2D:
 | 
					        case Pica::TexturingRegs::TextureConfig::Projection2D:
 | 
				
			||||||
            out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))";
 | 
					            out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))";
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
@ -308,7 +308,7 @@ static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) {
 | 
				
			|||||||
/// Writes the code to emulate the specified TEV stage
 | 
					/// Writes the code to emulate the specified TEV stage
 | 
				
			||||||
static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) {
 | 
					static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) {
 | 
				
			||||||
    const auto stage =
 | 
					    const auto stage =
 | 
				
			||||||
        static_cast<const Pica::Regs::TevStageConfig>(config.state.tev_stages[index]);
 | 
					        static_cast<const Pica::TexturingRegs::TevStageConfig>(config.state.tev_stages[index]);
 | 
				
			||||||
    if (!IsPassThroughTevStage(stage)) {
 | 
					    if (!IsPassThroughTevStage(stage)) {
 | 
				
			||||||
        std::string index_name = std::to_string(index);
 | 
					        std::string index_name = std::to_string(index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -674,7 +674,7 @@ vec4 secondary_fragment_color = vec4(0.0);
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Append fog combiner
 | 
					    // Append fog combiner
 | 
				
			||||||
    if (state.fog_mode == Regs::FogMode::Fog) {
 | 
					    if (state.fog_mode == Pica::TexturingRegs::FogMode::Fog) {
 | 
				
			||||||
        // Get index into fog LUT
 | 
					        // Get index into fog LUT
 | 
				
			||||||
        if (state.fog_flip) {
 | 
					        if (state.fog_flip) {
 | 
				
			||||||
            out += "float fog_index = (1.0 - depth) * 128.0;\n";
 | 
					            out += "float fog_index = (1.0 - depth) * 128.0;\n";
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ using GLvec4 = std::array<GLfloat, 4>;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace PicaToGL {
 | 
					namespace PicaToGL {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) {
 | 
					inline GLenum TextureFilterMode(Pica::TexturingRegs::TextureConfig::TextureFilter mode) {
 | 
				
			||||||
    static const GLenum filter_mode_table[] = {
 | 
					    static const GLenum filter_mode_table[] = {
 | 
				
			||||||
        GL_NEAREST, // TextureFilter::Nearest
 | 
					        GL_NEAREST, // TextureFilter::Nearest
 | 
				
			||||||
        GL_LINEAR,  // TextureFilter::Linear
 | 
					        GL_LINEAR,  // TextureFilter::Linear
 | 
				
			||||||
@ -47,7 +47,7 @@ inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) {
 | 
				
			|||||||
    return gl_mode;
 | 
					    return gl_mode;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) {
 | 
					inline GLenum WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) {
 | 
				
			||||||
    static const GLenum wrap_mode_table[] = {
 | 
					    static const GLenum wrap_mode_table[] = {
 | 
				
			||||||
        GL_CLAMP_TO_EDGE,   // WrapMode::ClampToEdge
 | 
					        GL_CLAMP_TO_EDGE,   // WrapMode::ClampToEdge
 | 
				
			||||||
        GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder
 | 
					        GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder
 | 
				
			||||||
 | 
				
			|||||||
@ -10,12 +10,12 @@
 | 
				
			|||||||
#include "common/math_util.h"
 | 
					#include "common/math_util.h"
 | 
				
			||||||
#include "common/swap.h"
 | 
					#include "common/swap.h"
 | 
				
			||||||
#include "common/vector_math.h"
 | 
					#include "common/vector_math.h"
 | 
				
			||||||
#include "video_core/pica.h"
 | 
					#include "video_core/regs_texturing.h"
 | 
				
			||||||
#include "video_core/texture/etc1.h"
 | 
					#include "video_core/texture/etc1.h"
 | 
				
			||||||
#include "video_core/texture/texture_decode.h"
 | 
					#include "video_core/texture/texture_decode.h"
 | 
				
			||||||
#include "video_core/utils.h"
 | 
					#include "video_core/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using TextureFormat = Pica::Regs::TextureFormat;
 | 
					using TextureFormat = Pica::TexturingRegs::TextureFormat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Pica {
 | 
					namespace Pica {
 | 
				
			||||||
namespace Texture {
 | 
					namespace Texture {
 | 
				
			||||||
@ -82,32 +82,32 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
    using VideoCore::MortonInterleave;
 | 
					    using VideoCore::MortonInterleave;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (info.format) {
 | 
					    switch (info.format) {
 | 
				
			||||||
    case Regs::TextureFormat::RGBA8: {
 | 
					    case TextureFormat::RGBA8: {
 | 
				
			||||||
        auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4);
 | 
					        auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4);
 | 
				
			||||||
        return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
 | 
					        return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::RGB8: {
 | 
					    case TextureFormat::RGB8: {
 | 
				
			||||||
        auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3);
 | 
					        auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3);
 | 
				
			||||||
        return {res.r(), res.g(), res.b(), 255};
 | 
					        return {res.r(), res.g(), res.b(), 255};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::RGB5A1: {
 | 
					    case TextureFormat::RGB5A1: {
 | 
				
			||||||
        auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2);
 | 
					        auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2);
 | 
				
			||||||
        return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
 | 
					        return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::RGB565: {
 | 
					    case TextureFormat::RGB565: {
 | 
				
			||||||
        auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2);
 | 
					        auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2);
 | 
				
			||||||
        return {res.r(), res.g(), res.b(), 255};
 | 
					        return {res.r(), res.g(), res.b(), 255};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::RGBA4: {
 | 
					    case TextureFormat::RGBA4: {
 | 
				
			||||||
        auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2);
 | 
					        auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2);
 | 
				
			||||||
        return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
 | 
					        return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::IA8: {
 | 
					    case TextureFormat::IA8: {
 | 
				
			||||||
        const u8* source_ptr = source + MortonInterleave(x, y) * 2;
 | 
					        const u8* source_ptr = source + MortonInterleave(x, y) * 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (disable_alpha) {
 | 
					        if (disable_alpha) {
 | 
				
			||||||
@ -118,17 +118,17 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::RG8: {
 | 
					    case TextureFormat::RG8: {
 | 
				
			||||||
        auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2);
 | 
					        auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2);
 | 
				
			||||||
        return {res.r(), res.g(), 0, 255};
 | 
					        return {res.r(), res.g(), 0, 255};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::I8: {
 | 
					    case TextureFormat::I8: {
 | 
				
			||||||
        const u8* source_ptr = source + MortonInterleave(x, y);
 | 
					        const u8* source_ptr = source + MortonInterleave(x, y);
 | 
				
			||||||
        return {*source_ptr, *source_ptr, *source_ptr, 255};
 | 
					        return {*source_ptr, *source_ptr, *source_ptr, 255};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::A8: {
 | 
					    case TextureFormat::A8: {
 | 
				
			||||||
        const u8* source_ptr = source + MortonInterleave(x, y);
 | 
					        const u8* source_ptr = source + MortonInterleave(x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (disable_alpha) {
 | 
					        if (disable_alpha) {
 | 
				
			||||||
@ -138,7 +138,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::IA4: {
 | 
					    case TextureFormat::IA4: {
 | 
				
			||||||
        const u8* source_ptr = source + MortonInterleave(x, y);
 | 
					        const u8* source_ptr = source + MortonInterleave(x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4);
 | 
					        u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4);
 | 
				
			||||||
@ -152,7 +152,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::I4: {
 | 
					    case TextureFormat::I4: {
 | 
				
			||||||
        u32 morton_offset = MortonInterleave(x, y);
 | 
					        u32 morton_offset = MortonInterleave(x, y);
 | 
				
			||||||
        const u8* source_ptr = source + morton_offset / 2;
 | 
					        const u8* source_ptr = source + morton_offset / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -162,7 +162,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
        return {i, i, i, 255};
 | 
					        return {i, i, i, 255};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::A4: {
 | 
					    case TextureFormat::A4: {
 | 
				
			||||||
        u32 morton_offset = MortonInterleave(x, y);
 | 
					        u32 morton_offset = MortonInterleave(x, y);
 | 
				
			||||||
        const u8* source_ptr = source + morton_offset / 2;
 | 
					        const u8* source_ptr = source + morton_offset / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -176,9 +176,9 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case Regs::TextureFormat::ETC1:
 | 
					    case TextureFormat::ETC1:
 | 
				
			||||||
    case Regs::TextureFormat::ETC1A4: {
 | 
					    case TextureFormat::ETC1A4: {
 | 
				
			||||||
        bool has_alpha = (info.format == Regs::TextureFormat::ETC1A4);
 | 
					        bool has_alpha = (info.format == TextureFormat::ETC1A4);
 | 
				
			||||||
        size_t subtile_size = has_alpha ? 16 : 8;
 | 
					        size_t subtile_size = has_alpha ? 16 : 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // ETC1 further subdivides each 8x8 tile into four 4x4 subtiles
 | 
					        // ETC1 further subdivides each 8x8 tile into four 4x4 subtiles
 | 
				
			||||||
@ -214,8 +214,8 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config,
 | 
					TextureInfo TextureInfo::FromPicaRegister(const TexturingRegs::TextureConfig& config,
 | 
				
			||||||
                                          const Regs::TextureFormat& format) {
 | 
					                                          const TexturingRegs::TextureFormat& format) {
 | 
				
			||||||
    TextureInfo info;
 | 
					    TextureInfo info;
 | 
				
			||||||
    info.physical_address = config.GetPhysicalAddress();
 | 
					    info.physical_address = config.GetPhysicalAddress();
 | 
				
			||||||
    info.width = config.width;
 | 
					    info.width = config.width;
 | 
				
			||||||
 | 
				
			|||||||
@ -6,27 +6,27 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "common/common_types.h"
 | 
					#include "common/common_types.h"
 | 
				
			||||||
#include "common/vector_math.h"
 | 
					#include "common/vector_math.h"
 | 
				
			||||||
#include "video_core/pica.h"
 | 
					#include "video_core/regs_texturing.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Pica {
 | 
					namespace Pica {
 | 
				
			||||||
namespace Texture {
 | 
					namespace Texture {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns the byte size of a 8*8 tile of the specified texture format.
 | 
					/// Returns the byte size of a 8*8 tile of the specified texture format.
 | 
				
			||||||
size_t CalculateTileSize(Pica::Regs::TextureFormat format);
 | 
					size_t CalculateTileSize(TexturingRegs::TextureFormat format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TextureInfo {
 | 
					struct TextureInfo {
 | 
				
			||||||
    PAddr physical_address;
 | 
					    PAddr physical_address;
 | 
				
			||||||
    unsigned int width;
 | 
					    unsigned int width;
 | 
				
			||||||
    unsigned int height;
 | 
					    unsigned int height;
 | 
				
			||||||
    ptrdiff_t stride;
 | 
					    ptrdiff_t stride;
 | 
				
			||||||
    Pica::Regs::TextureFormat format;
 | 
					    TexturingRegs::TextureFormat format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static TextureInfo FromPicaRegister(const Pica::Regs::TextureConfig& config,
 | 
					    static TextureInfo FromPicaRegister(const TexturingRegs::TextureConfig& config,
 | 
				
			||||||
                                        const Pica::Regs::TextureFormat& format);
 | 
					                                        const TexturingRegs::TextureFormat& format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Calculates stride from format and width, assuming that the entire texture is contiguous.
 | 
					    /// Calculates stride from format and width, assuming that the entire texture is contiguous.
 | 
				
			||||||
    void SetDefaultStride() {
 | 
					    void SetDefaultStride() {
 | 
				
			||||||
        stride = Pica::Texture::CalculateTileSize(format) * (width / 8);
 | 
					        stride = CalculateTileSize(format) * (width / 8);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user