summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-01-27 20:51:59 -0800
committerGravatar Yuri Kunde Schlesner2017-02-04 13:59:09 -0800
commit9017093f58fb08b85cfb842f305efa667d62cecb (patch)
tree98a1e77b197a562a8f13565e62f2e8bb9220ff94 /src
parentVideoCore: Split rasterizer regs from Regs struct (diff)
downloadyuzu-9017093f58fb08b85cfb842f305efa667d62cecb.tar.gz
yuzu-9017093f58fb08b85cfb842f305efa667d62cecb.tar.xz
yuzu-9017093f58fb08b85cfb842f305efa667d62cecb.zip
VideoCore: Split texturing regs from Regs struct
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/graphics/graphics_cmdlists.cpp22
-rw-r--r--src/citra_qt/debugger/graphics/graphics_surface.cpp7
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/command_processor.cpp24
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp35
-rw-r--r--src/video_core/debug_utils/debug_utils.h8
-rw-r--r--src/video_core/pica.h352
-rw-r--r--src/video_core/rasterizer.cpp52
-rw-r--r--src/video_core/regs_texturing.h328
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp129
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h25
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp10
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h4
-rw-r--r--src/video_core/texture/texture_decode.cpp38
-rw-r--r--src/video_core/texture/texture_decode.h12
17 files changed, 548 insertions, 507 deletions
diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp
index ee79f0edf..adaa18cfc 100644
--- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp
+++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp
@@ -123,15 +123,16 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&
123void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { 123void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
124 const unsigned int command_id = 124 const unsigned int command_id =
125 list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); 125 list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
126 if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || 126 if (COMMAND_IN_RANGE(command_id, texturing.texture0) ||
127 COMMAND_IN_RANGE(command_id, texture2)) { 127 COMMAND_IN_RANGE(command_id, texturing.texture1) ||
128 COMMAND_IN_RANGE(command_id, texturing.texture2)) {
128 129
129 unsigned texture_index; 130 unsigned texture_index;
130 if (COMMAND_IN_RANGE(command_id, texture0)) { 131 if (COMMAND_IN_RANGE(command_id, texturing.texture0)) {
131 texture_index = 0; 132 texture_index = 0;
132 } else if (COMMAND_IN_RANGE(command_id, texture1)) { 133 } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) {
133 texture_index = 1; 134 texture_index = 1;
134 } else if (COMMAND_IN_RANGE(command_id, texture2)) { 135 } else if (COMMAND_IN_RANGE(command_id, texturing.texture2)) {
135 texture_index = 2; 136 texture_index = 2;
136 } else { 137 } else {
137 UNREACHABLE_MSG("Unknown texture command"); 138 UNREACHABLE_MSG("Unknown texture command");
@@ -146,19 +147,20 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
146 147
147 const unsigned int command_id = 148 const unsigned int command_id =
148 list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); 149 list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
149 if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || 150 if (COMMAND_IN_RANGE(command_id, texturing.texture0) ||
150 COMMAND_IN_RANGE(command_id, texture2)) { 151 COMMAND_IN_RANGE(command_id, texturing.texture1) ||
152 COMMAND_IN_RANGE(command_id, texturing.texture2)) {
151 153
152 unsigned texture_index; 154 unsigned texture_index;
153 if (COMMAND_IN_RANGE(command_id, texture0)) { 155 if (COMMAND_IN_RANGE(command_id, texturing.texture0)) {
154 texture_index = 0; 156 texture_index = 0;
155 } else if (COMMAND_IN_RANGE(command_id, texture1)) { 157 } else if (COMMAND_IN_RANGE(command_id, texturing.texture1)) {
156 texture_index = 1; 158 texture_index = 1;
157 } else { 159 } else {
158 texture_index = 2; 160 texture_index = 2;
159 } 161 }
160 162
161 const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; 163 const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index];
162 const auto config = texture.config; 164 const auto config = texture.config;
163 const auto format = texture.format; 165 const auto format = texture.format;
164 166
diff --git a/src/citra_qt/debugger/graphics/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp
index bd82b00d4..406a49f42 100644
--- a/src/citra_qt/debugger/graphics/graphics_surface.cpp
+++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp
@@ -512,7 +512,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
512 break; 512 break;
513 } 513 }
514 514
515 const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; 515 const auto texture = Pica::g_state.regs.texturing.GetTextures()[texture_index];
516 auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format); 516 auto info = Pica::Texture::TextureInfo::FromPicaRegister(texture.config, texture.format);
517 517
518 surface_address = info.physical_address; 518 surface_address = info.physical_address;
@@ -574,7 +574,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
574 info.physical_address = surface_address; 574 info.physical_address = surface_address;
575 info.width = surface_width; 575 info.width = surface_width;
576 info.height = surface_height; 576 info.height = surface_height;
577 info.format = static_cast<Pica::Regs::TextureFormat>(surface_format); 577 info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface_format);
578 info.SetDefaultStride(); 578 info.SetDefaultStride();
579 579
580 for (unsigned int y = 0; y < surface_height; ++y) { 580 for (unsigned int y = 0; y < surface_height; ++y) {
@@ -689,7 +689,8 @@ void GraphicsSurfaceWidget::SaveSurface() {
689 689
690unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) { 690unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) {
691 if (format <= Format::MaxTextureFormat) { 691 if (format <= Format::MaxTextureFormat) {
692 return Pica::Regs::NibblesPerPixel(static_cast<Pica::Regs::TextureFormat>(format)); 692 return Pica::TexturingRegs::NibblesPerPixel(
693 static_cast<Pica::TexturingRegs::TextureFormat>(format));
693 } 694 }
694 695
695 switch (format) { 696 switch (format) {
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 522d7cc13..c0358fc20 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -33,6 +33,7 @@ set(HEADERS
33 rasterizer.h 33 rasterizer.h
34 rasterizer_interface.h 34 rasterizer_interface.h
35 regs_rasterizer.h 35 regs_rasterizer.h
36 regs_texturing.h
36 renderer_base.h 37 renderer_base.h
37 renderer_opengl/gl_rasterizer.h 38 renderer_opengl/gl_rasterizer.h
38 renderer_opengl/gl_rasterizer_cache.h 39 renderer_opengl/gl_rasterizer_cache.h
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index b4a9f23cf..fa3432f60 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -225,13 +225,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
225 225
226 if (g_debug_context && g_debug_context->recorder) { 226 if (g_debug_context && g_debug_context->recorder) {
227 for (int i = 0; i < 3; ++i) { 227 for (int i = 0; i < 3; ++i) {
228 const auto texture = regs.GetTextures()[i]; 228 const auto texture = regs.texturing.GetTextures()[i];
229 if (!texture.enabled) 229 if (!texture.enabled)
230 continue; 230 continue;
231 231
232 u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); 232 u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
233 g_debug_context->recorder->MemoryAccessed( 233 g_debug_context->recorder->MemoryAccessed(
234 texture_data, Pica::Regs::NibblesPerPixel(texture.format) * 234 texture_data, Pica::TexturingRegs::NibblesPerPixel(texture.format) *
235 texture.config.width / 2 * texture.config.height, 235 texture.config.width / 2 * texture.config.height,
236 texture.config.GetPhysicalAddress()); 236 texture.config.GetPhysicalAddress());
237 } 237 }
@@ -438,16 +438,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
438 break; 438 break;
439 } 439 }
440 440
441 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8): 441 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8):
442 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9): 442 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9):
443 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea): 443 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea):
444 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb): 444 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb):
445 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec): 445 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec):
446 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed): 446 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed):
447 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee): 447 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee):
448 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): { 448 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef): {
449 g_state.fog.lut[regs.fog_lut_offset % 128].raw = value; 449 g_state.fog.lut[regs.texturing.fog_lut_offset % 128].raw = value;
450 regs.fog_lut_offset.Assign(regs.fog_lut_offset + 1); 450 regs.texturing.fog_lut_offset.Assign(regs.texturing.fog_lut_offset + 1);
451 break; 451 break;
452 } 452 }
453 453
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 618268654..81cd35cd9 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -331,7 +331,7 @@ static void FlushIOFile(png_structp png_ptr) {
331} 331}
332#endif 332#endif
333 333
334void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) { 334void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data) {
335#ifndef HAVE_PNG 335#ifndef HAVE_PNG
336 return; 336 return;
337#else 337#else
@@ -396,7 +396,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
396 info.width = texture_config.width; 396 info.width = texture_config.width;
397 info.height = texture_config.height; 397 info.height = texture_config.height;
398 info.stride = row_stride; 398 info.stride = row_stride;
399 info.format = g_state.regs.texture0_format; 399 info.format = g_state.regs.texturing.texture0_format;
400 Math::Vec4<u8> texture_color = Pica::Texture::LookupTexture(data, x, y, info); 400 Math::Vec4<u8> texture_color = Pica::Texture::LookupTexture(data, x, y, info);
401 buf[3 * x + y * row_stride] = texture_color.r(); 401 buf[3 * x + y * row_stride] = texture_color.r();
402 buf[3 * x + y * row_stride + 1] = texture_color.g(); 402 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
434 return ret; 434 return ret;
435} 435}
436 436
437static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfig::Source& source) { 437static std::string GetTevStageConfigSourceString(
438 using Source = Pica::Regs::TevStageConfig::Source; 438 const TexturingRegs::TevStageConfig::Source& source) {
439
440 using Source = TexturingRegs::TevStageConfig::Source;
439 static const std::map<Source, std::string> source_map = { 441 static const std::map<Source, std::string> source_map = {
440 {Source::PrimaryColor, "PrimaryColor"}, 442 {Source::PrimaryColor, "PrimaryColor"},
441 {Source::PrimaryFragmentColor, "PrimaryFragmentColor"}, 443 {Source::PrimaryFragmentColor, "PrimaryFragmentColor"},
@@ -457,9 +459,10 @@ static std::string GetTevStageConfigSourceString(const Pica::Regs::TevStageConfi
457} 459}
458 460
459static std::string GetTevStageConfigColorSourceString( 461static std::string GetTevStageConfigColorSourceString(
460 const Pica::Regs::TevStageConfig::Source& source, 462 const TexturingRegs::TevStageConfig::Source& source,
461 const Pica::Regs::TevStageConfig::ColorModifier modifier) { 463 const TexturingRegs::TevStageConfig::ColorModifier modifier) {
462 using ColorModifier = Pica::Regs::TevStageConfig::ColorModifier; 464
465 using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier;
463 static const std::map<ColorModifier, std::string> color_modifier_map = { 466 static const std::map<ColorModifier, std::string> color_modifier_map = {
464 {ColorModifier::SourceColor, "%source.rgb"}, 467 {ColorModifier::SourceColor, "%source.rgb"},
465 {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"}, 468 {ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"},
@@ -483,9 +486,10 @@ static std::string GetTevStageConfigColorSourceString(
483} 486}
484 487
485static std::string GetTevStageConfigAlphaSourceString( 488static std::string GetTevStageConfigAlphaSourceString(
486 const Pica::Regs::TevStageConfig::Source& source, 489 const TexturingRegs::TevStageConfig::Source& source,
487 const Pica::Regs::TevStageConfig::AlphaModifier modifier) { 490 const TexturingRegs::TevStageConfig::AlphaModifier modifier) {
488 using AlphaModifier = Pica::Regs::TevStageConfig::AlphaModifier; 491
492 using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier;
489 static const std::map<AlphaModifier, std::string> alpha_modifier_map = { 493 static const std::map<AlphaModifier, std::string> alpha_modifier_map = {
490 {AlphaModifier::SourceAlpha, "%source.a"}, 494 {AlphaModifier::SourceAlpha, "%source.a"},
491 {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"}, 495 {AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"},
@@ -507,8 +511,9 @@ static std::string GetTevStageConfigAlphaSourceString(
507} 511}
508 512
509static std::string GetTevStageConfigOperationString( 513static std::string GetTevStageConfigOperationString(
510 const Pica::Regs::TevStageConfig::Operation& operation) { 514 const TexturingRegs::TevStageConfig::Operation& operation) {
511 using Operation = Pica::Regs::TevStageConfig::Operation; 515
516 using Operation = TexturingRegs::TevStageConfig::Operation;
512 static const std::map<Operation, std::string> combiner_map = { 517 static const std::map<Operation, std::string> combiner_map = {
513 {Operation::Replace, "%source1"}, 518 {Operation::Replace, "%source1"},
514 {Operation::Modulate, "(%source1 * %source2)"}, 519 {Operation::Modulate, "(%source1 * %source2)"},
@@ -528,7 +533,7 @@ static std::string GetTevStageConfigOperationString(
528 return op_it->second; 533 return op_it->second;
529} 534}
530 535
531std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage) { 536std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage) {
532 auto op_str = GetTevStageConfigOperationString(tev_stage.color_op); 537 auto op_str = GetTevStageConfigOperationString(tev_stage.color_op);
533 op_str = ReplacePattern( 538 op_str = ReplacePattern(
534 op_str, "%source1", 539 op_str, "%source1",
@@ -541,7 +546,7 @@ std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfi
541 GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3)); 546 GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3));
542} 547}
543 548
544std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage) { 549std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage) {
545 auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op); 550 auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op);
546 op_str = ReplacePattern( 551 op_str = ReplacePattern(
547 op_str, "%source1", 552 op_str, "%source1",
@@ -554,7 +559,7 @@ std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfi
554 GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3)); 559 GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3));
555} 560}
556 561
557void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig, 6>& stages) { 562void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages) {
558 std::string stage_info = "Tev setup:\n"; 563 std::string stage_info = "Tev setup:\n";
559 for (size_t index = 0; index < stages.size(); ++index) { 564 for (size_t index = 0; index < stages.size(); ++index) {
560 const auto& tev_stage = stages[index]; 565 const auto& tev_stage = stages[index];
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 51270bc9c..e58b76d41 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -205,13 +205,13 @@ inline bool IsPicaTracing() {
205void OnPicaRegWrite(PicaTrace::Write write); 205void OnPicaRegWrite(PicaTrace::Write write);
206std::unique_ptr<PicaTrace> FinishPicaTracing(); 206std::unique_ptr<PicaTrace> FinishPicaTracing();
207 207
208void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data); 208void DumpTexture(const TexturingRegs::TextureConfig& texture_config, u8* data);
209 209
210std::string GetTevStageConfigColorCombinerString(const Pica::Regs::TevStageConfig& tev_stage); 210std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage);
211std::string GetTevStageConfigAlphaCombinerString(const Pica::Regs::TevStageConfig& tev_stage); 211std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage);
212 212
213/// Dumps the Tev stage config to log at trace level 213/// Dumps the Tev stage config to log at trace level
214void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig, 6>& stages); 214void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages);
215 215
216/** 216/**
217 * Used in the vertex loader to merge access records. TODO: Investigate if actually useful. 217 * Used in the vertex loader to merge access records. TODO: Investigate if actually useful.
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 9d7262b43..71194198a 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -19,6 +19,7 @@
19#include "common/logging/log.h" 19#include "common/logging/log.h"
20#include "common/vector_math.h" 20#include "common/vector_math.h"
21#include "video_core/regs_rasterizer.h" 21#include "video_core/regs_rasterizer.h"
22#include "video_core/regs_texturing.h"
22 23
23namespace Pica { 24namespace Pica {
24 25
@@ -49,81 +50,7 @@ struct Regs {
49 u32 trigger_irq; 50 u32 trigger_irq;
50 INSERT_PADDING_WORDS(0x2f); 51 INSERT_PADDING_WORDS(0x2f);
51 RasterizerRegs rasterizer; 52 RasterizerRegs rasterizer;
52 53 TexturingRegs texturing;
53 struct TextureConfig {
54 enum TextureType : u32 {
55 Texture2D = 0,
56 TextureCube = 1,
57 Shadow2D = 2,
58 Projection2D = 3,
59 ShadowCube = 4,
60 Disabled = 5,
61 };
62
63 enum WrapMode : u32 {
64 ClampToEdge = 0,
65 ClampToBorder = 1,
66 Repeat = 2,
67 MirroredRepeat = 3,
68 };
69
70 enum TextureFilter : u32 {
71 Nearest = 0,
72 Linear = 1,
73 };
74
75 union {
76 u32 raw;
77 BitField<0, 8, u32> r;
78 BitField<8, 8, u32> g;
79 BitField<16, 8, u32> b;
80 BitField<24, 8, u32> a;
81 } border_color;
82
83 union {
84 BitField<0, 16, u32> height;
85 BitField<16, 16, u32> width;
86 };
87
88 union {
89 BitField<1, 1, TextureFilter> mag_filter;
90 BitField<2, 1, TextureFilter> min_filter;
91 BitField<8, 2, WrapMode> wrap_t;
92 BitField<12, 2, WrapMode> wrap_s;
93 BitField<28, 2, TextureType>
94 type; ///< @note Only valid for texture 0 according to 3DBrew.
95 };
96
97 INSERT_PADDING_WORDS(0x1);
98
99 u32 address;
100
101 u32 GetPhysicalAddress() const {
102 return DecodeAddressRegister(address);
103 }
104
105 // texture1 and texture2 store the texture format directly after the address
106 // whereas texture0 inserts some additional flags inbetween.
107 // Hence, we store the format separately so that all other parameters can be described
108 // in a single structure.
109 };
110
111 enum class TextureFormat : u32 {
112 RGBA8 = 0,
113 RGB8 = 1,
114 RGB5A1 = 2,
115 RGB565 = 3,
116 RGBA4 = 4,
117 IA8 = 5,
118 RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
119 I8 = 7,
120 A8 = 8,
121 IA4 = 9,
122 I4 = 10,
123 A4 = 11,
124 ETC1 = 12, // compressed
125 ETC1A4 = 13, // compressed
126 };
127 54
128 enum class LogicOp : u32 { 55 enum class LogicOp : u32 {
129 Clear = 0, 56 Clear = 0,
@@ -144,239 +71,6 @@ struct Regs {
144 OrInverted = 15, 71 OrInverted = 15,
145 }; 72 };
146 73
147 static unsigned NibblesPerPixel(TextureFormat format) {
148 switch (format) {
149 case TextureFormat::RGBA8:
150 return 8;
151
152 case TextureFormat::RGB8:
153 return 6;
154
155 case TextureFormat::RGB5A1:
156 case TextureFormat::RGB565:
157 case TextureFormat::RGBA4:
158 case TextureFormat::IA8:
159 case TextureFormat::RG8:
160 return 4;
161
162 case TextureFormat::I4:
163 case TextureFormat::A4:
164 return 1;
165
166 case TextureFormat::I8:
167 case TextureFormat::A8:
168 case TextureFormat::IA4:
169 return 2;
170
171 default: // placeholder for yet unknown formats
172 UNIMPLEMENTED();
173 return 0;
174 }
175 }
176
177 union {
178 BitField<0, 1, u32> texture0_enable;
179 BitField<1, 1, u32> texture1_enable;
180 BitField<2, 1, u32> texture2_enable;
181 };
182 TextureConfig texture0;
183 INSERT_PADDING_WORDS(0x8);
184 BitField<0, 4, TextureFormat> texture0_format;
185 BitField<0, 1, u32> fragment_lighting_enable;
186 INSERT_PADDING_WORDS(0x1);
187 TextureConfig texture1;
188 BitField<0, 4, TextureFormat> texture1_format;
189 INSERT_PADDING_WORDS(0x2);
190 TextureConfig texture2;
191 BitField<0, 4, TextureFormat> texture2_format;
192 INSERT_PADDING_WORDS(0x21);
193
194 struct FullTextureConfig {
195 const bool enabled;
196 const TextureConfig config;
197 const TextureFormat format;
198 };
199 const std::array<FullTextureConfig, 3> GetTextures() const {
200 return {{
201 {texture0_enable.ToBool(), texture0, texture0_format},
202 {texture1_enable.ToBool(), texture1, texture1_format},
203 {texture2_enable.ToBool(), texture2, texture2_format},
204 }};
205 }
206
207 // 0xc0-0xff: Texture Combiner (akin to glTexEnv)
208 struct TevStageConfig {
209 enum class Source : u32 {
210 PrimaryColor = 0x0,
211 PrimaryFragmentColor = 0x1,
212 SecondaryFragmentColor = 0x2,
213
214 Texture0 = 0x3,
215 Texture1 = 0x4,
216 Texture2 = 0x5,
217 Texture3 = 0x6,
218
219 PreviousBuffer = 0xd,
220 Constant = 0xe,
221 Previous = 0xf,
222 };
223
224 enum class ColorModifier : u32 {
225 SourceColor = 0x0,
226 OneMinusSourceColor = 0x1,
227 SourceAlpha = 0x2,
228 OneMinusSourceAlpha = 0x3,
229 SourceRed = 0x4,
230 OneMinusSourceRed = 0x5,
231
232 SourceGreen = 0x8,
233 OneMinusSourceGreen = 0x9,
234
235 SourceBlue = 0xc,
236 OneMinusSourceBlue = 0xd,
237 };
238
239 enum class AlphaModifier : u32 {
240 SourceAlpha = 0x0,
241 OneMinusSourceAlpha = 0x1,
242 SourceRed = 0x2,
243 OneMinusSourceRed = 0x3,
244 SourceGreen = 0x4,
245 OneMinusSourceGreen = 0x5,
246 SourceBlue = 0x6,
247 OneMinusSourceBlue = 0x7,
248 };
249
250 enum class Operation : u32 {
251 Replace = 0,
252 Modulate = 1,
253 Add = 2,
254 AddSigned = 3,
255 Lerp = 4,
256 Subtract = 5,
257 Dot3_RGB = 6,
258
259 MultiplyThenAdd = 8,
260 AddThenMultiply = 9,
261 };
262
263 union {
264 u32 sources_raw;
265 BitField<0, 4, Source> color_source1;
266 BitField<4, 4, Source> color_source2;
267 BitField<8, 4, Source> color_source3;
268 BitField<16, 4, Source> alpha_source1;
269 BitField<20, 4, Source> alpha_source2;
270 BitField<24, 4, Source> alpha_source3;
271 };
272
273 union {
274 u32 modifiers_raw;
275 BitField<0, 4, ColorModifier> color_modifier1;
276 BitField<4, 4, ColorModifier> color_modifier2;
277 BitField<8, 4, ColorModifier> color_modifier3;
278 BitField<12, 3, AlphaModifier> alpha_modifier1;
279 BitField<16, 3, AlphaModifier> alpha_modifier2;
280 BitField<20, 3, AlphaModifier> alpha_modifier3;
281 };
282
283 union {
284 u32 ops_raw;
285 BitField<0, 4, Operation> color_op;
286 BitField<16, 4, Operation> alpha_op;
287 };
288
289 union {
290 u32 const_color;
291 BitField<0, 8, u32> const_r;
292 BitField<8, 8, u32> const_g;
293 BitField<16, 8, u32> const_b;
294 BitField<24, 8, u32> const_a;
295 };
296
297 union {
298 u32 scales_raw;
299 BitField<0, 2, u32> color_scale;
300 BitField<16, 2, u32> alpha_scale;
301 };
302
303 inline unsigned GetColorMultiplier() const {
304 return (color_scale < 3) ? (1 << color_scale) : 1;
305 }
306
307 inline unsigned GetAlphaMultiplier() const {
308 return (alpha_scale < 3) ? (1 << alpha_scale) : 1;
309 }
310 };
311
312 TevStageConfig tev_stage0;
313 INSERT_PADDING_WORDS(0x3);
314 TevStageConfig tev_stage1;
315 INSERT_PADDING_WORDS(0x3);
316 TevStageConfig tev_stage2;
317 INSERT_PADDING_WORDS(0x3);
318 TevStageConfig tev_stage3;
319 INSERT_PADDING_WORDS(0x3);
320
321 enum class FogMode : u32 {
322 None = 0,
323 Fog = 5,
324 Gas = 7,
325 };
326
327 union {
328 BitField<0, 3, FogMode> fog_mode;
329 BitField<16, 1, u32> fog_flip;
330
331 union {
332 // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
333 // these masks are set
334 BitField<8, 4, u32> update_mask_rgb;
335 BitField<12, 4, u32> update_mask_a;
336
337 bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
338 return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
339 }
340
341 bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
342 return (stage_index < 4) && (update_mask_a & (1 << stage_index));
343 }
344 } tev_combiner_buffer_input;
345 };
346
347 union {
348 u32 raw;
349 BitField<0, 8, u32> r;
350 BitField<8, 8, u32> g;
351 BitField<16, 8, u32> b;
352 } fog_color;
353
354 INSERT_PADDING_WORDS(0x4);
355
356 BitField<0, 16, u32> fog_lut_offset;
357
358 INSERT_PADDING_WORDS(0x1);
359
360 u32 fog_lut_data[8];
361
362 TevStageConfig tev_stage4;
363 INSERT_PADDING_WORDS(0x3);
364 TevStageConfig tev_stage5;
365
366 union {
367 u32 raw;
368 BitField<0, 8, u32> r;
369 BitField<8, 8, u32> g;
370 BitField<16, 8, u32> b;
371 BitField<24, 8, u32> a;
372 } tev_combiner_buffer_color;
373
374 INSERT_PADDING_WORDS(0x2);
375
376 const std::array<Regs::TevStageConfig, 6> GetTevStages() const {
377 return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}};
378 };
379
380 enum class BlendEquation : u32 { 74 enum class BlendEquation : u32 {
381 Add = 0, 75 Add = 0,
382 Subtract = 1, 76 Subtract = 1,
@@ -1241,26 +935,28 @@ ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65);
1241ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68); 935ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68);
1242ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D); 936ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D);
1243 937
1244ASSERT_REG_POSITION(texture0_enable, 0x80); 938ASSERT_REG_POSITION(texturing, 0x80);
1245ASSERT_REG_POSITION(texture0, 0x81); 939ASSERT_REG_POSITION(texturing.texture0_enable, 0x80);
1246ASSERT_REG_POSITION(texture0_format, 0x8e); 940ASSERT_REG_POSITION(texturing.texture0, 0x81);
1247ASSERT_REG_POSITION(fragment_lighting_enable, 0x8f); 941ASSERT_REG_POSITION(texturing.texture0_format, 0x8e);
1248ASSERT_REG_POSITION(texture1, 0x91); 942ASSERT_REG_POSITION(texturing.fragment_lighting_enable, 0x8f);
1249ASSERT_REG_POSITION(texture1_format, 0x96); 943ASSERT_REG_POSITION(texturing.texture1, 0x91);
1250ASSERT_REG_POSITION(texture2, 0x99); 944ASSERT_REG_POSITION(texturing.texture1_format, 0x96);
1251ASSERT_REG_POSITION(texture2_format, 0x9e); 945ASSERT_REG_POSITION(texturing.texture2, 0x99);
1252ASSERT_REG_POSITION(tev_stage0, 0xc0); 946ASSERT_REG_POSITION(texturing.texture2_format, 0x9e);
1253ASSERT_REG_POSITION(tev_stage1, 0xc8); 947ASSERT_REG_POSITION(texturing.tev_stage0, 0xc0);
1254ASSERT_REG_POSITION(tev_stage2, 0xd0); 948ASSERT_REG_POSITION(texturing.tev_stage1, 0xc8);
1255ASSERT_REG_POSITION(tev_stage3, 0xd8); 949ASSERT_REG_POSITION(texturing.tev_stage2, 0xd0);
1256ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0); 950ASSERT_REG_POSITION(texturing.tev_stage3, 0xd8);
1257ASSERT_REG_POSITION(fog_mode, 0xe0); 951ASSERT_REG_POSITION(texturing.tev_combiner_buffer_input, 0xe0);
1258ASSERT_REG_POSITION(fog_color, 0xe1); 952ASSERT_REG_POSITION(texturing.fog_mode, 0xe0);
1259ASSERT_REG_POSITION(fog_lut_offset, 0xe6); 953ASSERT_REG_POSITION(texturing.fog_color, 0xe1);
1260ASSERT_REG_POSITION(fog_lut_data, 0xe8); 954ASSERT_REG_POSITION(texturing.fog_lut_offset, 0xe6);
1261ASSERT_REG_POSITION(tev_stage4, 0xf0); 955ASSERT_REG_POSITION(texturing.fog_lut_data, 0xe8);
1262ASSERT_REG_POSITION(tev_stage5, 0xf8); 956ASSERT_REG_POSITION(texturing.tev_stage4, 0xf0);
1263ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd); 957ASSERT_REG_POSITION(texturing.tev_stage5, 0xf8);
958ASSERT_REG_POSITION(texturing.tev_combiner_buffer_color, 0xfd);
959
1264ASSERT_REG_POSITION(output_merger, 0x100); 960ASSERT_REG_POSITION(output_merger, 0x100);
1265ASSERT_REG_POSITION(framebuffer, 0x110); 961ASSERT_REG_POSITION(framebuffer, 0x110);
1266ASSERT_REG_POSITION(lighting, 0x140); 962ASSERT_REG_POSITION(lighting, 0x140);
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index f82873480..48bc26571 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -397,8 +397,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
397 397
398 auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); 398 auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
399 399
400 auto textures = regs.GetTextures(); 400 auto textures = regs.texturing.GetTextures();
401 auto tev_stages = regs.GetTevStages(); 401 auto tev_stages = regs.texturing.GetTevStages();
402 402
403 bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable && 403 bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable &&
404 g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8; 404 g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8;
@@ -515,9 +515,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
515 // TODO: Refactor so cubemaps and shadowmaps can be handled 515 // TODO: Refactor so cubemaps and shadowmaps can be handled
516 if (i == 0) { 516 if (i == 0) {
517 switch (texture.config.type) { 517 switch (texture.config.type) {
518 case Regs::TextureConfig::Texture2D: 518 case TexturingRegs::TextureConfig::Texture2D:
519 break; 519 break;
520 case Regs::TextureConfig::Projection2D: { 520 case TexturingRegs::TextureConfig::Projection2D: {
521 auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); 521 auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w);
522 u /= tc0_w; 522 u /= tc0_w;
523 v /= tc0_w; 523 v /= tc0_w;
@@ -536,21 +536,21 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
536 int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height))) 536 int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height)))
537 .ToFloat32(); 537 .ToFloat32();
538 538
539 static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, 539 static auto GetWrappedTexCoord = [](TexturingRegs::TextureConfig::WrapMode mode,
540 unsigned size) { 540 int val, unsigned size) {
541 switch (mode) { 541 switch (mode) {
542 case Regs::TextureConfig::ClampToEdge: 542 case TexturingRegs::TextureConfig::ClampToEdge:
543 val = std::max(val, 0); 543 val = std::max(val, 0);
544 val = std::min(val, (int)size - 1); 544 val = std::min(val, (int)size - 1);
545 return val; 545 return val;
546 546
547 case Regs::TextureConfig::ClampToBorder: 547 case TexturingRegs::TextureConfig::ClampToBorder:
548 return val; 548 return val;
549 549
550 case Regs::TextureConfig::Repeat: 550 case TexturingRegs::TextureConfig::Repeat:
551 return (int)((unsigned)val % size); 551 return (int)((unsigned)val % size);
552 552
553 case Regs::TextureConfig::MirroredRepeat: { 553 case TexturingRegs::TextureConfig::MirroredRepeat: {
554 unsigned int coord = ((unsigned)val % (2 * size)); 554 unsigned int coord = ((unsigned)val % (2 * size));
555 if (coord >= size) 555 if (coord >= size)
556 coord = 2 * size - 1 - coord; 556 coord = 2 * size - 1 - coord;
@@ -564,9 +564,9 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
564 } 564 }
565 }; 565 };
566 566
567 if ((texture.config.wrap_s == Regs::TextureConfig::ClampToBorder && 567 if ((texture.config.wrap_s == TexturingRegs::TextureConfig::ClampToBorder &&
568 (s < 0 || static_cast<u32>(s) >= texture.config.width)) || 568 (s < 0 || static_cast<u32>(s) >= texture.config.width)) ||
569 (texture.config.wrap_t == Regs::TextureConfig::ClampToBorder && 569 (texture.config.wrap_t == TexturingRegs::TextureConfig::ClampToBorder &&
570 (t < 0 || static_cast<u32>(t) >= texture.config.height))) { 570 (t < 0 || static_cast<u32>(t) >= texture.config.height))) {
571 auto border_color = texture.config.border_color; 571 auto border_color = texture.config.border_color;
572 texture_color[i] = {border_color.r, border_color.g, border_color.b, 572 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
602 Math::Vec4<u8> combiner_output; 602 Math::Vec4<u8> combiner_output;
603 Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; 603 Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0};
604 Math::Vec4<u8> next_combiner_buffer = { 604 Math::Vec4<u8> next_combiner_buffer = {
605 regs.tev_combiner_buffer_color.r, regs.tev_combiner_buffer_color.g, 605 regs.texturing.tev_combiner_buffer_color.r,
606 regs.tev_combiner_buffer_color.b, regs.tev_combiner_buffer_color.a, 606 regs.texturing.tev_combiner_buffer_color.g,
607 regs.texturing.tev_combiner_buffer_color.b,
608 regs.texturing.tev_combiner_buffer_color.a,
607 }; 609 };
608 610
609 for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size(); 611 for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size();
610 ++tev_stage_index) { 612 ++tev_stage_index) {
611 const auto& tev_stage = tev_stages[tev_stage_index]; 613 const auto& tev_stage = tev_stages[tev_stage_index];
612 using Source = Regs::TevStageConfig::Source; 614 using Source = TexturingRegs::TevStageConfig::Source;
613 using ColorModifier = Regs::TevStageConfig::ColorModifier; 615 using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier;
614 using AlphaModifier = Regs::TevStageConfig::AlphaModifier; 616 using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier;
615 using Operation = Regs::TevStageConfig::Operation; 617 using Operation = TexturingRegs::TevStageConfig::Operation;
616 618
617 auto GetSource = [&](Source source) -> Math::Vec4<u8> { 619 auto GetSource = [&](Source source) -> Math::Vec4<u8> {
618 switch (source) { 620 switch (source) {
@@ -864,14 +866,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
864 866
865 combiner_buffer = next_combiner_buffer; 867 combiner_buffer = next_combiner_buffer;
866 868
867 if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor( 869 if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(
868 tev_stage_index)) { 870 tev_stage_index)) {
869 next_combiner_buffer.r() = combiner_output.r(); 871 next_combiner_buffer.r() = combiner_output.r();
870 next_combiner_buffer.g() = combiner_output.g(); 872 next_combiner_buffer.g() = combiner_output.g();
871 next_combiner_buffer.b() = combiner_output.b(); 873 next_combiner_buffer.b() = combiner_output.b();
872 } 874 }
873 875
874 if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha( 876 if (regs.texturing.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(
875 tev_stage_index)) { 877 tev_stage_index)) {
876 next_combiner_buffer.a() = combiner_output.a(); 878 next_combiner_buffer.a() = combiner_output.a();
877 } 879 }
@@ -924,16 +926,16 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve
924 // Not fully accurate. We'd have to know what data type is used to 926 // Not fully accurate. We'd have to know what data type is used to
925 // store the depth etc. Using float for now until we know more 927 // store the depth etc. Using float for now until we know more
926 // about Pica datatypes 928 // about Pica datatypes
927 if (regs.fog_mode == Regs::FogMode::Fog) { 929 if (regs.texturing.fog_mode == TexturingRegs::FogMode::Fog) {
928 const Math::Vec3<u8> fog_color = { 930 const Math::Vec3<u8> fog_color = {
929 static_cast<u8>(regs.fog_color.r.Value()), 931 static_cast<u8>(regs.texturing.fog_color.r.Value()),
930 static_cast<u8>(regs.fog_color.g.Value()), 932 static_cast<u8>(regs.texturing.fog_color.g.Value()),
931 static_cast<u8>(regs.fog_color.b.Value()), 933 static_cast<u8>(regs.texturing.fog_color.b.Value()),
932 }; 934 };
933 935
934 // Get index into fog LUT 936 // Get index into fog LUT
935 float fog_index; 937 float fog_index;
936 if (g_state.regs.fog_flip) { 938 if (g_state.regs.texturing.fog_flip) {
937 fog_index = (1.0f - depth) * 128.0f; 939 fog_index = (1.0f - depth) * 128.0f;
938 } else { 940 } else {
939 fog_index = depth * 128.0f; 941 fog_index = depth * 128.0f;
diff --git a/src/video_core/regs_texturing.h b/src/video_core/regs_texturing.h
new file mode 100644
index 000000000..be8bc6826
--- /dev/null
+++ b/src/video_core/regs_texturing.h
@@ -0,0 +1,328 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include "common/assert.h"
10#include "common/bit_field.h"
11#include "common/common_funcs.h"
12#include "common/common_types.h"
13
14namespace Pica {
15
16struct TexturingRegs {
17 struct TextureConfig {
18 enum TextureType : u32 {
19 Texture2D = 0,
20 TextureCube = 1,
21 Shadow2D = 2,
22 Projection2D = 3,
23 ShadowCube = 4,
24 Disabled = 5,
25 };
26
27 enum WrapMode : u32 {
28 ClampToEdge = 0,
29 ClampToBorder = 1,
30 Repeat = 2,
31 MirroredRepeat = 3,
32 };
33
34 enum TextureFilter : u32 {
35 Nearest = 0,
36 Linear = 1,
37 };
38
39 union {
40 u32 raw;
41 BitField<0, 8, u32> r;
42 BitField<8, 8, u32> g;
43 BitField<16, 8, u32> b;
44 BitField<24, 8, u32> a;
45 } border_color;
46
47 union {
48 BitField<0, 16, u32> height;
49 BitField<16, 16, u32> width;
50 };
51
52 union {
53 BitField<1, 1, TextureFilter> mag_filter;
54 BitField<2, 1, TextureFilter> min_filter;
55 BitField<8, 2, WrapMode> wrap_t;
56 BitField<12, 2, WrapMode> wrap_s;
57 BitField<28, 2, TextureType>
58 type; ///< @note Only valid for texture 0 according to 3DBrew.
59 };
60
61 INSERT_PADDING_WORDS(0x1);
62
63 u32 address;
64
65 PAddr GetPhysicalAddress() const {
66 return address * 8;
67 }
68
69 // texture1 and texture2 store the texture format directly after the address
70 // whereas texture0 inserts some additional flags inbetween.
71 // Hence, we store the format separately so that all other parameters can be described
72 // in a single structure.
73 };
74
75 enum class TextureFormat : u32 {
76 RGBA8 = 0,
77 RGB8 = 1,
78 RGB5A1 = 2,
79 RGB565 = 3,
80 RGBA4 = 4,
81 IA8 = 5,
82 RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
83 I8 = 7,
84 A8 = 8,
85 IA4 = 9,
86 I4 = 10,
87 A4 = 11,
88 ETC1 = 12, // compressed
89 ETC1A4 = 13, // compressed
90 };
91
92 static unsigned NibblesPerPixel(TextureFormat format) {
93 switch (format) {
94 case TextureFormat::RGBA8:
95 return 8;
96
97 case TextureFormat::RGB8:
98 return 6;
99
100 case TextureFormat::RGB5A1:
101 case TextureFormat::RGB565:
102 case TextureFormat::RGBA4:
103 case TextureFormat::IA8:
104 case TextureFormat::RG8:
105 return 4;
106
107 case TextureFormat::I4:
108 case TextureFormat::A4:
109 return 1;
110
111 case TextureFormat::I8:
112 case TextureFormat::A8:
113 case TextureFormat::IA4:
114
115 default: // placeholder for yet unknown formats
116 UNIMPLEMENTED();
117 return 0;
118 }
119 }
120
121 union {
122 BitField<0, 1, u32> texture0_enable;
123 BitField<1, 1, u32> texture1_enable;
124 BitField<2, 1, u32> texture2_enable;
125 };
126 TextureConfig texture0;
127 INSERT_PADDING_WORDS(0x8);
128 BitField<0, 4, TextureFormat> texture0_format;
129 BitField<0, 1, u32> fragment_lighting_enable;
130 INSERT_PADDING_WORDS(0x1);
131 TextureConfig texture1;
132 BitField<0, 4, TextureFormat> texture1_format;
133 INSERT_PADDING_WORDS(0x2);
134 TextureConfig texture2;
135 BitField<0, 4, TextureFormat> texture2_format;
136 INSERT_PADDING_WORDS(0x21);
137
138 struct FullTextureConfig {
139 const bool enabled;
140 const TextureConfig config;
141 const TextureFormat format;
142 };
143 const std::array<FullTextureConfig, 3> GetTextures() const {
144 return {{
145 {texture0_enable.ToBool(), texture0, texture0_format},
146 {texture1_enable.ToBool(), texture1, texture1_format},
147 {texture2_enable.ToBool(), texture2, texture2_format},
148 }};
149 }
150
151 // 0xc0-0xff: Texture Combiner (akin to glTexEnv)
152 struct TevStageConfig {
153 enum class Source : u32 {
154 PrimaryColor = 0x0,
155 PrimaryFragmentColor = 0x1,
156 SecondaryFragmentColor = 0x2,
157
158 Texture0 = 0x3,
159 Texture1 = 0x4,
160 Texture2 = 0x5,
161 Texture3 = 0x6,
162
163 PreviousBuffer = 0xd,
164 Constant = 0xe,
165 Previous = 0xf,
166 };
167
168 enum class ColorModifier : u32 {
169 SourceColor = 0x0,
170 OneMinusSourceColor = 0x1,
171 SourceAlpha = 0x2,
172 OneMinusSourceAlpha = 0x3,
173 SourceRed = 0x4,
174 OneMinusSourceRed = 0x5,
175
176 SourceGreen = 0x8,
177 OneMinusSourceGreen = 0x9,
178
179 SourceBlue = 0xc,
180 OneMinusSourceBlue = 0xd,
181 };
182
183 enum class AlphaModifier : u32 {
184 SourceAlpha = 0x0,
185 OneMinusSourceAlpha = 0x1,
186 SourceRed = 0x2,
187 OneMinusSourceRed = 0x3,
188 SourceGreen = 0x4,
189 OneMinusSourceGreen = 0x5,
190 SourceBlue = 0x6,
191 OneMinusSourceBlue = 0x7,
192 };
193
194 enum class Operation : u32 {
195 Replace = 0,
196 Modulate = 1,
197 Add = 2,
198 AddSigned = 3,
199 Lerp = 4,
200 Subtract = 5,
201 Dot3_RGB = 6,
202
203 MultiplyThenAdd = 8,
204 AddThenMultiply = 9,
205 };
206
207 union {
208 u32 sources_raw;
209 BitField<0, 4, Source> color_source1;
210 BitField<4, 4, Source> color_source2;
211 BitField<8, 4, Source> color_source3;
212 BitField<16, 4, Source> alpha_source1;
213 BitField<20, 4, Source> alpha_source2;
214 BitField<24, 4, Source> alpha_source3;
215 };
216
217 union {
218 u32 modifiers_raw;
219 BitField<0, 4, ColorModifier> color_modifier1;
220 BitField<4, 4, ColorModifier> color_modifier2;
221 BitField<8, 4, ColorModifier> color_modifier3;
222 BitField<12, 3, AlphaModifier> alpha_modifier1;
223 BitField<16, 3, AlphaModifier> alpha_modifier2;
224 BitField<20, 3, AlphaModifier> alpha_modifier3;
225 };
226
227 union {
228 u32 ops_raw;
229 BitField<0, 4, Operation> color_op;
230 BitField<16, 4, Operation> alpha_op;
231 };
232
233 union {
234 u32 const_color;
235 BitField<0, 8, u32> const_r;
236 BitField<8, 8, u32> const_g;
237 BitField<16, 8, u32> const_b;
238 BitField<24, 8, u32> const_a;
239 };
240
241 union {
242 u32 scales_raw;
243 BitField<0, 2, u32> color_scale;
244 BitField<16, 2, u32> alpha_scale;
245 };
246
247 inline unsigned GetColorMultiplier() const {
248 return (color_scale < 3) ? (1 << color_scale) : 1;
249 }
250
251 inline unsigned GetAlphaMultiplier() const {
252 return (alpha_scale < 3) ? (1 << alpha_scale) : 1;
253 }
254 };
255
256 TevStageConfig tev_stage0;
257 INSERT_PADDING_WORDS(0x3);
258 TevStageConfig tev_stage1;
259 INSERT_PADDING_WORDS(0x3);
260 TevStageConfig tev_stage2;
261 INSERT_PADDING_WORDS(0x3);
262 TevStageConfig tev_stage3;
263 INSERT_PADDING_WORDS(0x3);
264
265 enum class FogMode : u32 {
266 None = 0,
267 Fog = 5,
268 Gas = 7,
269 };
270
271 union {
272 BitField<0, 3, FogMode> fog_mode;
273 BitField<16, 1, u32> fog_flip;
274
275 union {
276 // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
277 // these masks are set
278 BitField<8, 4, u32> update_mask_rgb;
279 BitField<12, 4, u32> update_mask_a;
280
281 bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
282 return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
283 }
284
285 bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
286 return (stage_index < 4) && (update_mask_a & (1 << stage_index));
287 }
288 } tev_combiner_buffer_input;
289 };
290
291 union {
292 u32 raw;
293 BitField<0, 8, u32> r;
294 BitField<8, 8, u32> g;
295 BitField<16, 8, u32> b;
296 } fog_color;
297
298 INSERT_PADDING_WORDS(0x4);
299
300 BitField<0, 16, u32> fog_lut_offset;
301
302 INSERT_PADDING_WORDS(0x1);
303
304 u32 fog_lut_data[8];
305
306 TevStageConfig tev_stage4;
307 INSERT_PADDING_WORDS(0x3);
308 TevStageConfig tev_stage5;
309
310 union {
311 u32 raw;
312 BitField<0, 8, u32> r;
313 BitField<8, 8, u32> g;
314 BitField<16, 8, u32> b;
315 BitField<24, 8, u32> a;
316 } tev_combiner_buffer_color;
317
318 INSERT_PADDING_WORDS(0x2);
319
320 const std::array<TevStageConfig, 6> GetTevStages() const {
321 return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}};
322 };
323};
324
325static_assert(sizeof(TexturingRegs) == 0x80 * sizeof(u32),
326 "TexturingRegs struct has incorrect size");
327
328} // namespace Pica
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index c4061c005..f7eaa17e2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -26,13 +26,15 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
26MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); 26MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
27MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); 27MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
28 28
29static bool IsPassThroughTevStage(const Pica::Regs::TevStageConfig& stage) { 29static bool IsPassThroughTevStage(const Pica::TexturingRegs::TevStageConfig& stage) {
30 return (stage.color_op == Pica::Regs::TevStageConfig::Operation::Replace && 30 using TevStageConfig = Pica::TexturingRegs::TevStageConfig;
31 stage.alpha_op == Pica::Regs::TevStageConfig::Operation::Replace && 31
32 stage.color_source1 == Pica::Regs::TevStageConfig::Source::Previous && 32 return (stage.color_op == TevStageConfig::Operation::Replace &&
33 stage.alpha_source1 == Pica::Regs::TevStageConfig::Source::Previous && 33 stage.alpha_op == TevStageConfig::Operation::Replace &&
34 stage.color_modifier1 == Pica::Regs::TevStageConfig::ColorModifier::SourceColor && 34 stage.color_source1 == TevStageConfig::Source::Previous &&
35 stage.alpha_modifier1 == Pica::Regs::TevStageConfig::AlphaModifier::SourceAlpha && 35 stage.alpha_source1 == TevStageConfig::Source::Previous &&
36 stage.color_modifier1 == TevStageConfig::ColorModifier::SourceColor &&
37 stage.alpha_modifier1 == TevStageConfig::AlphaModifier::SourceAlpha &&
36 stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1); 38 stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1);
37} 39}
38 40
@@ -242,7 +244,7 @@ void RasterizerOpenGL::DrawTriangles() {
242 } 244 }
243 245
244 // Sync and bind the texture surfaces 246 // Sync and bind the texture surfaces
245 const auto pica_textures = regs.GetTextures(); 247 const auto pica_textures = regs.texturing.GetTextures();
246 for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) { 248 for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
247 const auto& texture = pica_textures[texture_index]; 249 const auto& texture = pica_textures[texture_index];
248 250
@@ -348,17 +350,17 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
348 break; 350 break;
349 351
350 // Fog state 352 // Fog state
351 case PICA_REG_INDEX(fog_color): 353 case PICA_REG_INDEX(texturing.fog_color):
352 SyncFogColor(); 354 SyncFogColor();
353 break; 355 break;
354 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8): 356 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[0], 0xe8):
355 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9): 357 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[1], 0xe9):
356 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea): 358 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[2], 0xea):
357 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb): 359 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[3], 0xeb):
358 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec): 360 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[4], 0xec):
359 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed): 361 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[5], 0xed):
360 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee): 362 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[6], 0xee):
361 case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef): 363 case PICA_REG_INDEX_WORKAROUND(texturing.fog_lut_data[7], 0xef):
362 uniform_block_data.fog_lut_dirty = true; 364 uniform_block_data.fog_lut_dirty = true;
363 break; 365 break;
364 366
@@ -411,60 +413,60 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
411 break; 413 break;
412 414
413 // Texture 0 type 415 // Texture 0 type
414 case PICA_REG_INDEX(texture0.type): 416 case PICA_REG_INDEX(texturing.texture0.type):
415 shader_dirty = true; 417 shader_dirty = true;
416 break; 418 break;
417 419
418 // TEV stages 420 // TEV stages
419 // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input) 421 // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input)
420 case PICA_REG_INDEX(tev_stage0.color_source1): 422 case PICA_REG_INDEX(texturing.tev_stage0.color_source1):
421 case PICA_REG_INDEX(tev_stage0.color_modifier1): 423 case PICA_REG_INDEX(texturing.tev_stage0.color_modifier1):
422 case PICA_REG_INDEX(tev_stage0.color_op): 424 case PICA_REG_INDEX(texturing.tev_stage0.color_op):
423 case PICA_REG_INDEX(tev_stage0.color_scale): 425 case PICA_REG_INDEX(texturing.tev_stage0.color_scale):
424 case PICA_REG_INDEX(tev_stage1.color_source1): 426 case PICA_REG_INDEX(texturing.tev_stage1.color_source1):
425 case PICA_REG_INDEX(tev_stage1.color_modifier1): 427 case PICA_REG_INDEX(texturing.tev_stage1.color_modifier1):
426 case PICA_REG_INDEX(tev_stage1.color_op): 428 case PICA_REG_INDEX(texturing.tev_stage1.color_op):
427 case PICA_REG_INDEX(tev_stage1.color_scale): 429 case PICA_REG_INDEX(texturing.tev_stage1.color_scale):
428 case PICA_REG_INDEX(tev_stage2.color_source1): 430 case PICA_REG_INDEX(texturing.tev_stage2.color_source1):
429 case PICA_REG_INDEX(tev_stage2.color_modifier1): 431 case PICA_REG_INDEX(texturing.tev_stage2.color_modifier1):
430 case PICA_REG_INDEX(tev_stage2.color_op): 432 case PICA_REG_INDEX(texturing.tev_stage2.color_op):
431 case PICA_REG_INDEX(tev_stage2.color_scale): 433 case PICA_REG_INDEX(texturing.tev_stage2.color_scale):
432 case PICA_REG_INDEX(tev_stage3.color_source1): 434 case PICA_REG_INDEX(texturing.tev_stage3.color_source1):
433 case PICA_REG_INDEX(tev_stage3.color_modifier1): 435 case PICA_REG_INDEX(texturing.tev_stage3.color_modifier1):
434 case PICA_REG_INDEX(tev_stage3.color_op): 436 case PICA_REG_INDEX(texturing.tev_stage3.color_op):
435 case PICA_REG_INDEX(tev_stage3.color_scale): 437 case PICA_REG_INDEX(texturing.tev_stage3.color_scale):
436 case PICA_REG_INDEX(tev_stage4.color_source1): 438 case PICA_REG_INDEX(texturing.tev_stage4.color_source1):
437 case PICA_REG_INDEX(tev_stage4.color_modifier1): 439 case PICA_REG_INDEX(texturing.tev_stage4.color_modifier1):
438 case PICA_REG_INDEX(tev_stage4.color_op): 440 case PICA_REG_INDEX(texturing.tev_stage4.color_op):
439 case PICA_REG_INDEX(tev_stage4.color_scale): 441 case PICA_REG_INDEX(texturing.tev_stage4.color_scale):
440 case PICA_REG_INDEX(tev_stage5.color_source1): 442 case PICA_REG_INDEX(texturing.tev_stage5.color_source1):
441 case PICA_REG_INDEX(tev_stage5.color_modifier1): 443 case PICA_REG_INDEX(texturing.tev_stage5.color_modifier1):
442 case PICA_REG_INDEX(tev_stage5.color_op): 444 case PICA_REG_INDEX(texturing.tev_stage5.color_op):
443 case PICA_REG_INDEX(tev_stage5.color_scale): 445 case PICA_REG_INDEX(texturing.tev_stage5.color_scale):
444 case PICA_REG_INDEX(tev_combiner_buffer_input): 446 case PICA_REG_INDEX(texturing.tev_combiner_buffer_input):
445 shader_dirty = true; 447 shader_dirty = true;
446 break; 448 break;
447 case PICA_REG_INDEX(tev_stage0.const_r): 449 case PICA_REG_INDEX(texturing.tev_stage0.const_r):
448 SyncTevConstColor(0, regs.tev_stage0); 450 SyncTevConstColor(0, regs.texturing.tev_stage0);
449 break; 451 break;
450 case PICA_REG_INDEX(tev_stage1.const_r): 452 case PICA_REG_INDEX(texturing.tev_stage1.const_r):
451 SyncTevConstColor(1, regs.tev_stage1); 453 SyncTevConstColor(1, regs.texturing.tev_stage1);
452 break; 454 break;
453 case PICA_REG_INDEX(tev_stage2.const_r): 455 case PICA_REG_INDEX(texturing.tev_stage2.const_r):
454 SyncTevConstColor(2, regs.tev_stage2); 456 SyncTevConstColor(2, regs.texturing.tev_stage2);
455 break; 457 break;
456 case PICA_REG_INDEX(tev_stage3.const_r): 458 case PICA_REG_INDEX(texturing.tev_stage3.const_r):
457 SyncTevConstColor(3, regs.tev_stage3); 459 SyncTevConstColor(3, regs.texturing.tev_stage3);
458 break; 460 break;
459 case PICA_REG_INDEX(tev_stage4.const_r): 461 case PICA_REG_INDEX(texturing.tev_stage4.const_r):
460 SyncTevConstColor(4, regs.tev_stage4); 462 SyncTevConstColor(4, regs.texturing.tev_stage4);
461 break; 463 break;
462 case PICA_REG_INDEX(tev_stage5.const_r): 464 case PICA_REG_INDEX(texturing.tev_stage5.const_r):
463 SyncTevConstColor(5, regs.tev_stage5); 465 SyncTevConstColor(5, regs.texturing.tev_stage5);
464 break; 466 break;
465 467
466 // TEV combiner buffer color 468 // TEV combiner buffer color
467 case PICA_REG_INDEX(tev_combiner_buffer_color): 469 case PICA_REG_INDEX(texturing.tev_combiner_buffer_color):
468 SyncCombinerColor(); 470 SyncCombinerColor();
469 break; 471 break;
470 472
@@ -979,7 +981,9 @@ void RasterizerOpenGL::SamplerInfo::Create() {
979 // Other attributes have correct defaults 981 // Other attributes have correct defaults
980} 982}
981 983
982void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Pica::Regs::TextureConfig& config) { 984void RasterizerOpenGL::SamplerInfo::SyncWithConfig(
985 const Pica::TexturingRegs::TextureConfig& config) {
986
983 GLuint s = sampler.handle; 987 GLuint s = sampler.handle;
984 988
985 if (mag_filter != config.mag_filter) { 989 if (mag_filter != config.mag_filter) {
@@ -1091,7 +1095,7 @@ void RasterizerOpenGL::SetShader() {
1091 SyncDepthOffset(); 1095 SyncDepthOffset();
1092 SyncAlphaTest(); 1096 SyncAlphaTest();
1093 SyncCombinerColor(); 1097 SyncCombinerColor();
1094 auto& tev_stages = Pica::g_state.regs.GetTevStages(); 1098 auto& tev_stages = Pica::g_state.regs.texturing.GetTevStages();
1095 for (int index = 0; index < tev_stages.size(); ++index) 1099 for (int index = 0; index < tev_stages.size(); ++index)
1096 SyncTevConstColor(index, tev_stages[index]); 1100 SyncTevConstColor(index, tev_stages[index]);
1097 1101
@@ -1182,8 +1186,8 @@ void RasterizerOpenGL::SyncBlendColor() {
1182void RasterizerOpenGL::SyncFogColor() { 1186void RasterizerOpenGL::SyncFogColor() {
1183 const auto& regs = Pica::g_state.regs; 1187 const auto& regs = Pica::g_state.regs;
1184 uniform_block_data.data.fog_color = { 1188 uniform_block_data.data.fog_color = {
1185 regs.fog_color.r.Value() / 255.0f, regs.fog_color.g.Value() / 255.0f, 1189 regs.texturing.fog_color.r.Value() / 255.0f, regs.texturing.fog_color.g.Value() / 255.0f,
1186 regs.fog_color.b.Value() / 255.0f, 1190 regs.texturing.fog_color.b.Value() / 255.0f,
1187 }; 1191 };
1188 uniform_block_data.dirty = true; 1192 uniform_block_data.dirty = true;
1189} 1193}
@@ -1267,7 +1271,8 @@ void RasterizerOpenGL::SyncDepthTest() {
1267} 1271}
1268 1272
1269void RasterizerOpenGL::SyncCombinerColor() { 1273void RasterizerOpenGL::SyncCombinerColor() {
1270 auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw); 1274 auto combiner_color =
1275 PicaToGL::ColorRGBA8(Pica::g_state.regs.texturing.tev_combiner_buffer_color.raw);
1271 if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) { 1276 if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
1272 uniform_block_data.data.tev_combiner_buffer_color = combiner_color; 1277 uniform_block_data.data.tev_combiner_buffer_color = combiner_color;
1273 uniform_block_data.dirty = true; 1278 uniform_block_data.dirty = true;
@@ -1275,7 +1280,7 @@ void RasterizerOpenGL::SyncCombinerColor() {
1275} 1280}
1276 1281
1277void RasterizerOpenGL::SyncTevConstColor(int stage_index, 1282void RasterizerOpenGL::SyncTevConstColor(int stage_index,
1278 const Pica::Regs::TevStageConfig& tev_stage) { 1283 const Pica::TexturingRegs::TevStageConfig& tev_stage) {
1279 auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color); 1284 auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color);
1280 if (const_color != uniform_block_data.data.const_color[stage_index]) { 1285 if (const_color != uniform_block_data.data.const_color[stage_index]) {
1281 uniform_block_data.data.const_color[stage_index] = const_color; 1286 uniform_block_data.data.const_color[stage_index] = const_color;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index bd7b6874a..519df6478 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -60,12 +60,12 @@ union PicaShaderConfig {
60 ? regs.output_merger.alpha_test.func.Value() 60 ? regs.output_merger.alpha_test.func.Value()
61 : Pica::Regs::CompareFunc::Always; 61 : Pica::Regs::CompareFunc::Always;
62 62
63 state.texture0_type = regs.texture0.type; 63 state.texture0_type = regs.texturing.texture0.type;
64 64
65 // Copy relevant tev stages fields. 65 // Copy relevant tev stages fields.
66 // We don't sync const_color here because of the high variance, it is a 66 // We don't sync const_color here because of the high variance, it is a
67 // shader uniform instead. 67 // shader uniform instead.
68 const auto& tev_stages = regs.GetTevStages(); 68 const auto& tev_stages = regs.texturing.GetTevStages();
69 DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size()); 69 DEBUG_ASSERT(state.tev_stages.size() == tev_stages.size());
70 for (size_t i = 0; i < tev_stages.size(); i++) { 70 for (size_t i = 0; i < tev_stages.size(); i++) {
71 const auto& tev_stage = tev_stages[i]; 71 const auto& tev_stage = tev_stages[i];
@@ -75,11 +75,12 @@ union PicaShaderConfig {
75 state.tev_stages[i].scales_raw = tev_stage.scales_raw; 75 state.tev_stages[i].scales_raw = tev_stage.scales_raw;
76 } 76 }
77 77
78 state.fog_mode = regs.fog_mode; 78 state.fog_mode = regs.texturing.fog_mode;
79 state.fog_flip = regs.fog_flip != 0; 79 state.fog_flip = regs.texturing.fog_flip != 0;
80 80
81 state.combiner_buffer_input = regs.tev_combiner_buffer_input.update_mask_rgb.Value() | 81 state.combiner_buffer_input =
82 regs.tev_combiner_buffer_input.update_mask_a.Value() << 4; 82 regs.texturing.tev_combiner_buffer_input.update_mask_rgb.Value() |
83 regs.texturing.tev_combiner_buffer_input.update_mask_a.Value() << 4;
83 84
84 // Fragment lighting 85 // Fragment lighting
85 86
@@ -159,8 +160,8 @@ union PicaShaderConfig {
159 u32 modifiers_raw; 160 u32 modifiers_raw;
160 u32 ops_raw; 161 u32 ops_raw;
161 u32 scales_raw; 162 u32 scales_raw;
162 explicit operator Pica::Regs::TevStageConfig() const noexcept { 163 explicit operator Pica::TexturingRegs::TevStageConfig() const noexcept {
163 Pica::Regs::TevStageConfig stage; 164 Pica::TexturingRegs::TevStageConfig stage;
164 stage.sources_raw = sources_raw; 165 stage.sources_raw = sources_raw;
165 stage.modifiers_raw = modifiers_raw; 166 stage.modifiers_raw = modifiers_raw;
166 stage.ops_raw = ops_raw; 167 stage.ops_raw = ops_raw;
@@ -173,12 +174,12 @@ union PicaShaderConfig {
173 struct State { 174 struct State {
174 Pica::Regs::CompareFunc alpha_test_func; 175 Pica::Regs::CompareFunc alpha_test_func;
175 Pica::RasterizerRegs::ScissorMode scissor_test_mode; 176 Pica::RasterizerRegs::ScissorMode scissor_test_mode;
176 Pica::Regs::TextureConfig::TextureType texture0_type; 177 Pica::TexturingRegs::TextureConfig::TextureType texture0_type;
177 std::array<TevStageConfigRaw, 6> tev_stages; 178 std::array<TevStageConfigRaw, 6> tev_stages;
178 u8 combiner_buffer_input; 179 u8 combiner_buffer_input;
179 180
180 Pica::RasterizerRegs::DepthBuffering depthmap_enable; 181 Pica::RasterizerRegs::DepthBuffering depthmap_enable;
181 Pica::Regs::FogMode fog_mode; 182 Pica::TexturingRegs::FogMode fog_mode;
182 bool fog_flip; 183 bool fog_flip;
183 184
184 struct { 185 struct {
@@ -251,7 +252,7 @@ public:
251 252
252private: 253private:
253 struct SamplerInfo { 254 struct SamplerInfo {
254 using TextureConfig = Pica::Regs::TextureConfig; 255 using TextureConfig = Pica::TexturingRegs::TextureConfig;
255 256
256 OGLSampler sampler; 257 OGLSampler sampler;
257 258
@@ -398,7 +399,7 @@ private:
398 void SyncCombinerColor(); 399 void SyncCombinerColor();
399 400
400 /// Syncs the TEV constant color to match the PICA register 401 /// Syncs the TEV constant color to match the PICA register
401 void SyncTevConstColor(int tev_index, const Pica::Regs::TevStageConfig& tev_stage); 402 void SyncTevConstColor(int tev_index, const Pica::TexturingRegs::TevStageConfig& tev_stage);
402 403
403 /// Syncs the lighting global ambient color to match the PICA register 404 /// Syncs the lighting global ambient color to match the PICA register
404 void SyncGlobalAmbient(); 405 void SyncGlobalAmbient();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 60380257a..6d08d1a67 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -342,7 +342,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo
342 Pica::Texture::TextureInfo tex_info; 342 Pica::Texture::TextureInfo tex_info;
343 tex_info.width = params.width; 343 tex_info.width = params.width;
344 tex_info.height = params.height; 344 tex_info.height = params.height;
345 tex_info.format = (Pica::Regs::TextureFormat)params.pixel_format; 345 tex_info.format = (Pica::TexturingRegs::TextureFormat)params.pixel_format;
346 tex_info.SetDefaultStride(); 346 tex_info.SetDefaultStride();
347 tex_info.physical_address = params.addr; 347 tex_info.physical_address = params.addr;
348 348
@@ -510,7 +510,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params
510} 510}
511 511
512CachedSurface* RasterizerCacheOpenGL::GetTextureSurface( 512CachedSurface* RasterizerCacheOpenGL::GetTextureSurface(
513 const Pica::Regs::FullTextureConfig& config) { 513 const Pica::TexturingRegs::FullTextureConfig& config) {
514 514
515 Pica::Texture::TextureInfo info = 515 Pica::Texture::TextureInfo info =
516 Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); 516 Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index f57fdb3cc..c354dfa33 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -96,7 +96,7 @@ struct CachedSurface {
96 return bpp_table[(unsigned int)format]; 96 return bpp_table[(unsigned int)format];
97 } 97 }
98 98
99 static PixelFormat PixelFormatFromTextureFormat(Pica::Regs::TextureFormat format) { 99 static PixelFormat PixelFormatFromTextureFormat(Pica::TexturingRegs::TextureFormat format) {
100 return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid; 100 return ((unsigned int)format < 14) ? (PixelFormat)format : PixelFormat::Invalid;
101 } 101 }
102 102
@@ -212,7 +212,7 @@ public:
212 bool load_if_create, MathUtil::Rectangle<int>& out_rect); 212 bool load_if_create, MathUtil::Rectangle<int>& out_rect);
213 213
214 /// Gets a surface based on the texture configuration 214 /// Gets a surface based on the texture configuration
215 CachedSurface* GetTextureSurface(const Pica::Regs::FullTextureConfig& config); 215 CachedSurface* GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config);
216 216
217 /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer 217 /// Gets the color and depth surfaces and rect (resolution scaled) based on the framebuffer
218 /// configuration 218 /// configuration
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index c34c3463f..c3b0fdcee 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -14,7 +14,7 @@
14 14
15using Pica::Regs; 15using Pica::Regs;
16using Pica::RasterizerRegs; 16using Pica::RasterizerRegs;
17using TevStageConfig = Regs::TevStageConfig; 17using TevStageConfig = Pica::TexturingRegs::TevStageConfig;
18 18
19namespace GLShader { 19namespace GLShader {
20 20
@@ -47,10 +47,10 @@ static void AppendSource(std::string& out, const PicaShaderConfig& config,
47 case Source::Texture0: 47 case Source::Texture0:
48 // Only unit 0 respects the texturing type (according to 3DBrew) 48 // Only unit 0 respects the texturing type (according to 3DBrew)
49 switch (state.texture0_type) { 49 switch (state.texture0_type) {
50 case Pica::Regs::TextureConfig::Texture2D: 50 case Pica::TexturingRegs::TextureConfig::Texture2D:
51 out += "texture(tex[0], texcoord[0])"; 51 out += "texture(tex[0], texcoord[0])";
52 break; 52 break;
53 case Pica::Regs::TextureConfig::Projection2D: 53 case Pica::TexturingRegs::TextureConfig::Projection2D:
54 out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))"; 54 out += "textureProj(tex[0], vec3(texcoord[0], texcoord0_w))";
55 break; 55 break;
56 default: 56 default:
@@ -308,7 +308,7 @@ static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) {
308/// Writes the code to emulate the specified TEV stage 308/// Writes the code to emulate the specified TEV stage
309static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) { 309static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) {
310 const auto stage = 310 const auto stage =
311 static_cast<const Pica::Regs::TevStageConfig>(config.state.tev_stages[index]); 311 static_cast<const Pica::TexturingRegs::TevStageConfig>(config.state.tev_stages[index]);
312 if (!IsPassThroughTevStage(stage)) { 312 if (!IsPassThroughTevStage(stage)) {
313 std::string index_name = std::to_string(index); 313 std::string index_name = std::to_string(index);
314 314
@@ -674,7 +674,7 @@ vec4 secondary_fragment_color = vec4(0.0);
674 } 674 }
675 675
676 // Append fog combiner 676 // Append fog combiner
677 if (state.fog_mode == Regs::FogMode::Fog) { 677 if (state.fog_mode == Pica::TexturingRegs::FogMode::Fog) {
678 // Get index into fog LUT 678 // Get index into fog LUT
679 if (state.fog_flip) { 679 if (state.fog_flip) {
680 out += "float fog_index = (1.0 - depth) * 128.0;\n"; 680 out += "float fog_index = (1.0 - depth) * 128.0;\n";
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index cc49867c8..37cfbd45a 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -20,7 +20,7 @@ using GLvec4 = std::array<GLfloat, 4>;
20 20
21namespace PicaToGL { 21namespace PicaToGL {
22 22
23inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) { 23inline GLenum TextureFilterMode(Pica::TexturingRegs::TextureConfig::TextureFilter mode) {
24 static const GLenum filter_mode_table[] = { 24 static const GLenum filter_mode_table[] = {
25 GL_NEAREST, // TextureFilter::Nearest 25 GL_NEAREST, // TextureFilter::Nearest
26 GL_LINEAR, // TextureFilter::Linear 26 GL_LINEAR, // TextureFilter::Linear
@@ -47,7 +47,7 @@ inline GLenum TextureFilterMode(Pica::Regs::TextureConfig::TextureFilter mode) {
47 return gl_mode; 47 return gl_mode;
48} 48}
49 49
50inline GLenum WrapMode(Pica::Regs::TextureConfig::WrapMode mode) { 50inline GLenum WrapMode(Pica::TexturingRegs::TextureConfig::WrapMode mode) {
51 static const GLenum wrap_mode_table[] = { 51 static const GLenum wrap_mode_table[] = {
52 GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge 52 GL_CLAMP_TO_EDGE, // WrapMode::ClampToEdge
53 GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder 53 GL_CLAMP_TO_BORDER, // WrapMode::ClampToBorder
diff --git a/src/video_core/texture/texture_decode.cpp b/src/video_core/texture/texture_decode.cpp
index f611a1aa9..40d363184 100644
--- a/src/video_core/texture/texture_decode.cpp
+++ b/src/video_core/texture/texture_decode.cpp
@@ -10,12 +10,12 @@
10#include "common/math_util.h" 10#include "common/math_util.h"
11#include "common/swap.h" 11#include "common/swap.h"
12#include "common/vector_math.h" 12#include "common/vector_math.h"
13#include "video_core/pica.h" 13#include "video_core/regs_texturing.h"
14#include "video_core/texture/etc1.h" 14#include "video_core/texture/etc1.h"
15#include "video_core/texture/texture_decode.h" 15#include "video_core/texture/texture_decode.h"
16#include "video_core/utils.h" 16#include "video_core/utils.h"
17 17
18using TextureFormat = Pica::Regs::TextureFormat; 18using TextureFormat = Pica::TexturingRegs::TextureFormat;
19 19
20namespace Pica { 20namespace Pica {
21namespace Texture { 21namespace Texture {
@@ -82,32 +82,32 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
82 using VideoCore::MortonInterleave; 82 using VideoCore::MortonInterleave;
83 83
84 switch (info.format) { 84 switch (info.format) {
85 case Regs::TextureFormat::RGBA8: { 85 case TextureFormat::RGBA8: {
86 auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4); 86 auto res = Color::DecodeRGBA8(source + MortonInterleave(x, y) * 4);
87 return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; 87 return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
88 } 88 }
89 89
90 case Regs::TextureFormat::RGB8: { 90 case TextureFormat::RGB8: {
91 auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3); 91 auto res = Color::DecodeRGB8(source + MortonInterleave(x, y) * 3);
92 return {res.r(), res.g(), res.b(), 255}; 92 return {res.r(), res.g(), res.b(), 255};
93 } 93 }
94 94
95 case Regs::TextureFormat::RGB5A1: { 95 case TextureFormat::RGB5A1: {
96 auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2); 96 auto res = Color::DecodeRGB5A1(source + MortonInterleave(x, y) * 2);
97 return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; 97 return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
98 } 98 }
99 99
100 case Regs::TextureFormat::RGB565: { 100 case TextureFormat::RGB565: {
101 auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2); 101 auto res = Color::DecodeRGB565(source + MortonInterleave(x, y) * 2);
102 return {res.r(), res.g(), res.b(), 255}; 102 return {res.r(), res.g(), res.b(), 255};
103 } 103 }
104 104
105 case Regs::TextureFormat::RGBA4: { 105 case TextureFormat::RGBA4: {
106 auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2); 106 auto res = Color::DecodeRGBA4(source + MortonInterleave(x, y) * 2);
107 return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())}; 107 return {res.r(), res.g(), res.b(), static_cast<u8>(disable_alpha ? 255 : res.a())};
108 } 108 }
109 109
110 case Regs::TextureFormat::IA8: { 110 case TextureFormat::IA8: {
111 const u8* source_ptr = source + MortonInterleave(x, y) * 2; 111 const u8* source_ptr = source + MortonInterleave(x, y) * 2;
112 112
113 if (disable_alpha) { 113 if (disable_alpha) {
@@ -118,17 +118,17 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
118 } 118 }
119 } 119 }
120 120
121 case Regs::TextureFormat::RG8: { 121 case TextureFormat::RG8: {
122 auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2); 122 auto res = Color::DecodeRG8(source + MortonInterleave(x, y) * 2);
123 return {res.r(), res.g(), 0, 255}; 123 return {res.r(), res.g(), 0, 255};
124 } 124 }
125 125
126 case Regs::TextureFormat::I8: { 126 case TextureFormat::I8: {
127 const u8* source_ptr = source + MortonInterleave(x, y); 127 const u8* source_ptr = source + MortonInterleave(x, y);
128 return {*source_ptr, *source_ptr, *source_ptr, 255}; 128 return {*source_ptr, *source_ptr, *source_ptr, 255};
129 } 129 }
130 130
131 case Regs::TextureFormat::A8: { 131 case TextureFormat::A8: {
132 const u8* source_ptr = source + MortonInterleave(x, y); 132 const u8* source_ptr = source + MortonInterleave(x, y);
133 133
134 if (disable_alpha) { 134 if (disable_alpha) {
@@ -138,7 +138,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
138 } 138 }
139 } 139 }
140 140
141 case Regs::TextureFormat::IA4: { 141 case TextureFormat::IA4: {
142 const u8* source_ptr = source + MortonInterleave(x, y); 142 const u8* source_ptr = source + MortonInterleave(x, y);
143 143
144 u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4); 144 u8 i = Color::Convert4To8(((*source_ptr) & 0xF0) >> 4);
@@ -152,7 +152,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
152 } 152 }
153 } 153 }
154 154
155 case Regs::TextureFormat::I4: { 155 case TextureFormat::I4: {
156 u32 morton_offset = MortonInterleave(x, y); 156 u32 morton_offset = MortonInterleave(x, y);
157 const u8* source_ptr = source + morton_offset / 2; 157 const u8* source_ptr = source + morton_offset / 2;
158 158
@@ -162,7 +162,7 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
162 return {i, i, i, 255}; 162 return {i, i, i, 255};
163 } 163 }
164 164
165 case Regs::TextureFormat::A4: { 165 case TextureFormat::A4: {
166 u32 morton_offset = MortonInterleave(x, y); 166 u32 morton_offset = MortonInterleave(x, y);
167 const u8* source_ptr = source + morton_offset / 2; 167 const u8* source_ptr = source + morton_offset / 2;
168 168
@@ -176,9 +176,9 @@ Math::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int
176 } 176 }
177 } 177 }
178 178
179 case Regs::TextureFormat::ETC1: 179 case TextureFormat::ETC1:
180 case Regs::TextureFormat::ETC1A4: { 180 case TextureFormat::ETC1A4: {
181 bool has_alpha = (info.format == Regs::TextureFormat::ETC1A4); 181 bool has_alpha = (info.format == TextureFormat::ETC1A4);
182 size_t subtile_size = has_alpha ? 16 : 8; 182 size_t subtile_size = has_alpha ? 16 : 8;
183 183
184 // ETC1 further subdivides each 8x8 tile into four 4x4 subtiles 184 // 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
214 } 214 }
215} 215}
216 216
217TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, 217TextureInfo TextureInfo::FromPicaRegister(const TexturingRegs::TextureConfig& config,
218 const Regs::TextureFormat& format) { 218 const TexturingRegs::TextureFormat& format) {
219 TextureInfo info; 219 TextureInfo info;
220 info.physical_address = config.GetPhysicalAddress(); 220 info.physical_address = config.GetPhysicalAddress();
221 info.width = config.width; 221 info.width = config.width;
diff --git a/src/video_core/texture/texture_decode.h b/src/video_core/texture/texture_decode.h
index 5c636939a..8507cfeb8 100644
--- a/src/video_core/texture/texture_decode.h
+++ b/src/video_core/texture/texture_decode.h
@@ -6,27 +6,27 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/vector_math.h" 8#include "common/vector_math.h"
9#include "video_core/pica.h" 9#include "video_core/regs_texturing.h"
10 10
11namespace Pica { 11namespace Pica {
12namespace Texture { 12namespace Texture {
13 13
14/// Returns the byte size of a 8*8 tile of the specified texture format. 14/// Returns the byte size of a 8*8 tile of the specified texture format.
15size_t CalculateTileSize(Pica::Regs::TextureFormat format); 15size_t CalculateTileSize(TexturingRegs::TextureFormat format);
16 16
17struct TextureInfo { 17struct TextureInfo {
18 PAddr physical_address; 18 PAddr physical_address;
19 unsigned int width; 19 unsigned int width;
20 unsigned int height; 20 unsigned int height;
21 ptrdiff_t stride; 21 ptrdiff_t stride;
22 Pica::Regs::TextureFormat format; 22 TexturingRegs::TextureFormat format;
23 23
24 static TextureInfo FromPicaRegister(const Pica::Regs::TextureConfig& config, 24 static TextureInfo FromPicaRegister(const TexturingRegs::TextureConfig& config,
25 const Pica::Regs::TextureFormat& format); 25 const TexturingRegs::TextureFormat& format);
26 26
27 /// Calculates stride from format and width, assuming that the entire texture is contiguous. 27 /// Calculates stride from format and width, assuming that the entire texture is contiguous.
28 void SetDefaultStride() { 28 void SetDefaultStride() {
29 stride = Pica::Texture::CalculateTileSize(format) * (width / 8); 29 stride = CalculateTileSize(format) * (width / 8);
30 } 30 }
31}; 31};
32 32