regs_texturing.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. // Copyright 2017 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include "common/assert.h"
  7. #include "common/bit_field.h"
  8. #include "common/common_funcs.h"
  9. #include "common/common_types.h"
  10. namespace Pica {
  11. struct TexturingRegs {
  12. struct TextureConfig {
  13. enum TextureType : u32 {
  14. Texture2D = 0,
  15. TextureCube = 1,
  16. Shadow2D = 2,
  17. Projection2D = 3,
  18. ShadowCube = 4,
  19. Disabled = 5,
  20. };
  21. enum WrapMode : u32 {
  22. ClampToEdge = 0,
  23. ClampToBorder = 1,
  24. Repeat = 2,
  25. MirroredRepeat = 3,
  26. // Mode 4-7 produces some weird result and may be just invalid:
  27. ClampToEdge2 = 4, // Positive coord: clamp to edge; negative coord: repeat
  28. ClampToBorder2 = 5, // Positive coord: clamp to border; negative coord: repeat
  29. Repeat2 = 6, // Same as Repeat
  30. Repeat3 = 7, // Same as Repeat
  31. };
  32. enum TextureFilter : u32 {
  33. Nearest = 0,
  34. Linear = 1,
  35. };
  36. union {
  37. u32 raw;
  38. BitField<0, 8, u32> r;
  39. BitField<8, 8, u32> g;
  40. BitField<16, 8, u32> b;
  41. BitField<24, 8, u32> a;
  42. } border_color;
  43. union {
  44. BitField<0, 11, u32> height;
  45. BitField<16, 11, u32> width;
  46. };
  47. union {
  48. BitField<1, 1, TextureFilter> mag_filter;
  49. BitField<2, 1, TextureFilter> min_filter;
  50. BitField<8, 3, WrapMode> wrap_t;
  51. BitField<12, 3, WrapMode> wrap_s;
  52. /// @note Only valid for texture 0 according to 3DBrew.
  53. BitField<28, 3, TextureType> type;
  54. };
  55. INSERT_PADDING_WORDS(0x1);
  56. BitField<0, 28, u32> address;
  57. PAddr GetPhysicalAddress() const {
  58. return address * 8;
  59. }
  60. // texture1 and texture2 store the texture format directly after the address
  61. // whereas texture0 inserts some additional flags inbetween.
  62. // Hence, we store the format separately so that all other parameters can be described
  63. // in a single structure.
  64. };
  65. enum class TextureFormat : u32 {
  66. RGBA8 = 0,
  67. RGB8 = 1,
  68. RGB5A1 = 2,
  69. RGB565 = 3,
  70. RGBA4 = 4,
  71. IA8 = 5,
  72. RG8 = 6, ///< @note Also called HILO8 in 3DBrew.
  73. I8 = 7,
  74. A8 = 8,
  75. IA4 = 9,
  76. I4 = 10,
  77. A4 = 11,
  78. ETC1 = 12, // compressed
  79. ETC1A4 = 13, // compressed
  80. };
  81. static unsigned NibblesPerPixel(TextureFormat format) {
  82. switch (format) {
  83. case TextureFormat::RGBA8:
  84. return 8;
  85. case TextureFormat::RGB8:
  86. return 6;
  87. case TextureFormat::RGB5A1:
  88. case TextureFormat::RGB565:
  89. case TextureFormat::RGBA4:
  90. case TextureFormat::IA8:
  91. case TextureFormat::RG8:
  92. return 4;
  93. case TextureFormat::I4:
  94. case TextureFormat::A4:
  95. return 1;
  96. case TextureFormat::I8:
  97. case TextureFormat::A8:
  98. case TextureFormat::IA4:
  99. default: // placeholder for yet unknown formats
  100. UNIMPLEMENTED();
  101. return 0;
  102. }
  103. }
  104. union {
  105. BitField<0, 1, u32> texture0_enable;
  106. BitField<1, 1, u32> texture1_enable;
  107. BitField<2, 1, u32> texture2_enable;
  108. BitField<8, 2, u32> texture3_coordinates;
  109. BitField<10, 1, u32> texture3_enable;
  110. BitField<13, 1, u32> texture2_use_coord1;
  111. BitField<16, 1, u32> clear_texture_cache; // TODO: unimplemented
  112. } main_config;
  113. TextureConfig texture0;
  114. enum class CubeFace {
  115. PositiveX = 0,
  116. NegativeX = 1,
  117. PositiveY = 2,
  118. NegativeY = 3,
  119. PositiveZ = 4,
  120. NegativeZ = 5,
  121. };
  122. BitField<0, 22, u32> cube_address[5];
  123. PAddr GetCubePhysicalAddress(CubeFace face) const {
  124. PAddr address = texture0.address;
  125. if (face != CubeFace::PositiveX) {
  126. // Bits [22:27] from the main texture address is shared with all cubemap additional
  127. // addresses.
  128. auto& face_addr = cube_address[static_cast<size_t>(face) - 1];
  129. address &= ~face_addr.mask;
  130. address |= face_addr;
  131. }
  132. // A multiplier of 8 is also needed in the same way as the main address.
  133. return address * 8;
  134. }
  135. INSERT_PADDING_WORDS(0x3);
  136. BitField<0, 4, TextureFormat> texture0_format;
  137. BitField<0, 1, u32> fragment_lighting_enable;
  138. INSERT_PADDING_WORDS(0x1);
  139. TextureConfig texture1;
  140. BitField<0, 4, TextureFormat> texture1_format;
  141. INSERT_PADDING_WORDS(0x2);
  142. TextureConfig texture2;
  143. BitField<0, 4, TextureFormat> texture2_format;
  144. INSERT_PADDING_WORDS(0x9);
  145. struct FullTextureConfig {
  146. const bool enabled;
  147. const TextureConfig config;
  148. const TextureFormat format;
  149. };
  150. const std::array<FullTextureConfig, 3> GetTextures() const {
  151. return {{
  152. {main_config.texture0_enable.ToBool(), texture0, texture0_format},
  153. {main_config.texture1_enable.ToBool(), texture1, texture1_format},
  154. {main_config.texture2_enable.ToBool(), texture2, texture2_format},
  155. }};
  156. }
  157. // 0xa8-0xad: ProcTex Config
  158. enum class ProcTexClamp : u32 {
  159. ToZero = 0,
  160. ToEdge = 1,
  161. SymmetricalRepeat = 2,
  162. MirroredRepeat = 3,
  163. Pulse = 4,
  164. };
  165. enum class ProcTexCombiner : u32 {
  166. U = 0, // u
  167. U2 = 1, // u * u
  168. V = 2, // v
  169. V2 = 3, // v * v
  170. Add = 4, // (u + v) / 2
  171. Add2 = 5, // (u * u + v * v) / 2
  172. SqrtAdd2 = 6, // sqrt(u * u + v * v)
  173. Min = 7, // min(u, v)
  174. Max = 8, // max(u, v)
  175. RMax = 9, // Average of Max and SqrtAdd2
  176. };
  177. enum class ProcTexShift : u32 {
  178. None = 0,
  179. Odd = 1,
  180. Even = 2,
  181. };
  182. union {
  183. BitField<0, 3, ProcTexClamp> u_clamp;
  184. BitField<3, 3, ProcTexClamp> v_clamp;
  185. BitField<6, 4, ProcTexCombiner> color_combiner;
  186. BitField<10, 4, ProcTexCombiner> alpha_combiner;
  187. BitField<14, 1, u32> separate_alpha;
  188. BitField<15, 1, u32> noise_enable;
  189. BitField<16, 2, ProcTexShift> u_shift;
  190. BitField<18, 2, ProcTexShift> v_shift;
  191. BitField<20, 8, u32> bias_low; // float16 TODO: unimplemented
  192. } proctex;
  193. union ProcTexNoiseConfig {
  194. BitField<0, 16, s32> amplitude; // fixed1.3.12
  195. BitField<16, 16, u32> phase; // float16
  196. };
  197. ProcTexNoiseConfig proctex_noise_u;
  198. ProcTexNoiseConfig proctex_noise_v;
  199. union {
  200. BitField<0, 16, u32> u; // float16
  201. BitField<16, 16, u32> v; // float16
  202. } proctex_noise_frequency;
  203. enum class ProcTexFilter : u32 {
  204. Nearest = 0,
  205. Linear = 1,
  206. NearestMipmapNearest = 2,
  207. LinearMipmapNearest = 3,
  208. NearestMipmapLinear = 4,
  209. LinearMipmapLinear = 5,
  210. };
  211. union {
  212. BitField<0, 3, ProcTexFilter> filter;
  213. BitField<11, 8, u32> width;
  214. BitField<19, 8, u32> bias_high; // TODO: unimplemented
  215. } proctex_lut;
  216. BitField<0, 8, u32> proctex_lut_offset;
  217. INSERT_PADDING_WORDS(0x1);
  218. // 0xaf-0xb7: ProcTex LUT
  219. enum class ProcTexLutTable : u32 {
  220. Noise = 0,
  221. ColorMap = 2,
  222. AlphaMap = 3,
  223. Color = 4,
  224. ColorDiff = 5,
  225. };
  226. union {
  227. BitField<0, 8, u32> index;
  228. BitField<8, 4, ProcTexLutTable> ref_table;
  229. } proctex_lut_config;
  230. u32 proctex_lut_data[8];
  231. INSERT_PADDING_WORDS(0x8);
  232. // 0xc0-0xff: Texture Combiner (akin to glTexEnv)
  233. struct TevStageConfig {
  234. enum class Source : u32 {
  235. PrimaryColor = 0x0,
  236. PrimaryFragmentColor = 0x1,
  237. SecondaryFragmentColor = 0x2,
  238. Texture0 = 0x3,
  239. Texture1 = 0x4,
  240. Texture2 = 0x5,
  241. Texture3 = 0x6,
  242. PreviousBuffer = 0xd,
  243. Constant = 0xe,
  244. Previous = 0xf,
  245. };
  246. enum class ColorModifier : u32 {
  247. SourceColor = 0x0,
  248. OneMinusSourceColor = 0x1,
  249. SourceAlpha = 0x2,
  250. OneMinusSourceAlpha = 0x3,
  251. SourceRed = 0x4,
  252. OneMinusSourceRed = 0x5,
  253. SourceGreen = 0x8,
  254. OneMinusSourceGreen = 0x9,
  255. SourceBlue = 0xc,
  256. OneMinusSourceBlue = 0xd,
  257. };
  258. enum class AlphaModifier : u32 {
  259. SourceAlpha = 0x0,
  260. OneMinusSourceAlpha = 0x1,
  261. SourceRed = 0x2,
  262. OneMinusSourceRed = 0x3,
  263. SourceGreen = 0x4,
  264. OneMinusSourceGreen = 0x5,
  265. SourceBlue = 0x6,
  266. OneMinusSourceBlue = 0x7,
  267. };
  268. enum class Operation : u32 {
  269. Replace = 0,
  270. Modulate = 1,
  271. Add = 2,
  272. AddSigned = 3,
  273. Lerp = 4,
  274. Subtract = 5,
  275. Dot3_RGB = 6,
  276. Dot3_RGBA = 7,
  277. MultiplyThenAdd = 8,
  278. AddThenMultiply = 9,
  279. };
  280. union {
  281. u32 sources_raw;
  282. BitField<0, 4, Source> color_source1;
  283. BitField<4, 4, Source> color_source2;
  284. BitField<8, 4, Source> color_source3;
  285. BitField<16, 4, Source> alpha_source1;
  286. BitField<20, 4, Source> alpha_source2;
  287. BitField<24, 4, Source> alpha_source3;
  288. };
  289. union {
  290. u32 modifiers_raw;
  291. BitField<0, 4, ColorModifier> color_modifier1;
  292. BitField<4, 4, ColorModifier> color_modifier2;
  293. BitField<8, 4, ColorModifier> color_modifier3;
  294. BitField<12, 3, AlphaModifier> alpha_modifier1;
  295. BitField<16, 3, AlphaModifier> alpha_modifier2;
  296. BitField<20, 3, AlphaModifier> alpha_modifier3;
  297. };
  298. union {
  299. u32 ops_raw;
  300. BitField<0, 4, Operation> color_op;
  301. BitField<16, 4, Operation> alpha_op;
  302. };
  303. union {
  304. u32 const_color;
  305. BitField<0, 8, u32> const_r;
  306. BitField<8, 8, u32> const_g;
  307. BitField<16, 8, u32> const_b;
  308. BitField<24, 8, u32> const_a;
  309. };
  310. union {
  311. u32 scales_raw;
  312. BitField<0, 2, u32> color_scale;
  313. BitField<16, 2, u32> alpha_scale;
  314. };
  315. inline unsigned GetColorMultiplier() const {
  316. return (color_scale < 3) ? (1 << color_scale) : 1;
  317. }
  318. inline unsigned GetAlphaMultiplier() const {
  319. return (alpha_scale < 3) ? (1 << alpha_scale) : 1;
  320. }
  321. };
  322. TevStageConfig tev_stage0;
  323. INSERT_PADDING_WORDS(0x3);
  324. TevStageConfig tev_stage1;
  325. INSERT_PADDING_WORDS(0x3);
  326. TevStageConfig tev_stage2;
  327. INSERT_PADDING_WORDS(0x3);
  328. TevStageConfig tev_stage3;
  329. INSERT_PADDING_WORDS(0x3);
  330. enum class FogMode : u32 {
  331. None = 0,
  332. Fog = 5,
  333. Gas = 7,
  334. };
  335. union {
  336. BitField<0, 3, FogMode> fog_mode;
  337. BitField<16, 1, u32> fog_flip;
  338. union {
  339. // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
  340. // these masks are set
  341. BitField<8, 4, u32> update_mask_rgb;
  342. BitField<12, 4, u32> update_mask_a;
  343. bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
  344. return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
  345. }
  346. bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
  347. return (stage_index < 4) && (update_mask_a & (1 << stage_index));
  348. }
  349. } tev_combiner_buffer_input;
  350. };
  351. union {
  352. u32 raw;
  353. BitField<0, 8, u32> r;
  354. BitField<8, 8, u32> g;
  355. BitField<16, 8, u32> b;
  356. } fog_color;
  357. INSERT_PADDING_WORDS(0x4);
  358. BitField<0, 16, u32> fog_lut_offset;
  359. INSERT_PADDING_WORDS(0x1);
  360. u32 fog_lut_data[8];
  361. TevStageConfig tev_stage4;
  362. INSERT_PADDING_WORDS(0x3);
  363. TevStageConfig tev_stage5;
  364. union {
  365. u32 raw;
  366. BitField<0, 8, u32> r;
  367. BitField<8, 8, u32> g;
  368. BitField<16, 8, u32> b;
  369. BitField<24, 8, u32> a;
  370. } tev_combiner_buffer_color;
  371. INSERT_PADDING_WORDS(0x2);
  372. const std::array<TevStageConfig, 6> GetTevStages() const {
  373. return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}};
  374. };
  375. };
  376. static_assert(sizeof(TexturingRegs) == 0x80 * sizeof(u32),
  377. "TexturingRegs struct has incorrect size");
  378. } // namespace Pica