rasterizer.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include <cmath>
  7. #include "common/assert.h"
  8. #include "common/bit_field.h"
  9. #include "common/color.h"
  10. #include "common/common_types.h"
  11. #include "common/logging/log.h"
  12. #include "common/math_util.h"
  13. #include "common/microprofile.h"
  14. #include "common/vector_math.h"
  15. #include "core/hw/gpu.h"
  16. #include "core/memory.h"
  17. #include "video_core/debug_utils/debug_utils.h"
  18. #include "video_core/pica.h"
  19. #include "video_core/pica_state.h"
  20. #include "video_core/pica_types.h"
  21. #include "video_core/rasterizer.h"
  22. #include "video_core/shader/shader.h"
  23. #include "video_core/utils.h"
  24. namespace Pica {
  25. namespace Rasterizer {
  26. static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
  27. const auto& framebuffer = g_state.regs.framebuffer;
  28. const PAddr addr = framebuffer.GetColorBufferPhysicalAddress();
  29. // Similarly to textures, the render framebuffer is laid out from bottom to top, too.
  30. // NOTE: The framebuffer height register contains the actual FB height minus one.
  31. y = framebuffer.height - y;
  32. const u32 coarse_y = y & ~7;
  33. u32 bytes_per_pixel =
  34. GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value()));
  35. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) +
  36. coarse_y * framebuffer.width * bytes_per_pixel;
  37. u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset;
  38. switch (framebuffer.color_format) {
  39. case Regs::ColorFormat::RGBA8:
  40. Color::EncodeRGBA8(color, dst_pixel);
  41. break;
  42. case Regs::ColorFormat::RGB8:
  43. Color::EncodeRGB8(color, dst_pixel);
  44. break;
  45. case Regs::ColorFormat::RGB5A1:
  46. Color::EncodeRGB5A1(color, dst_pixel);
  47. break;
  48. case Regs::ColorFormat::RGB565:
  49. Color::EncodeRGB565(color, dst_pixel);
  50. break;
  51. case Regs::ColorFormat::RGBA4:
  52. Color::EncodeRGBA4(color, dst_pixel);
  53. break;
  54. default:
  55. LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x",
  56. framebuffer.color_format.Value());
  57. UNIMPLEMENTED();
  58. }
  59. }
  60. static const Math::Vec4<u8> GetPixel(int x, int y) {
  61. const auto& framebuffer = g_state.regs.framebuffer;
  62. const PAddr addr = framebuffer.GetColorBufferPhysicalAddress();
  63. y = framebuffer.height - y;
  64. const u32 coarse_y = y & ~7;
  65. u32 bytes_per_pixel =
  66. GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value()));
  67. u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) +
  68. coarse_y * framebuffer.width * bytes_per_pixel;
  69. u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset;
  70. switch (framebuffer.color_format) {
  71. case Regs::ColorFormat::RGBA8:
  72. return Color::DecodeRGBA8(src_pixel);
  73. case Regs::ColorFormat::RGB8:
  74. return Color::DecodeRGB8(src_pixel);
  75. case Regs::ColorFormat::RGB5A1:
  76. return Color::DecodeRGB5A1(src_pixel);
  77. case Regs::ColorFormat::RGB565:
  78. return Color::DecodeRGB565(src_pixel);
  79. case Regs::ColorFormat::RGBA4:
  80. return Color::DecodeRGBA4(src_pixel);
  81. default:
  82. LOG_CRITICAL(Render_Software, "Unknown framebuffer color format %x",
  83. framebuffer.color_format.Value());
  84. UNIMPLEMENTED();
  85. }
  86. return {0, 0, 0, 0};
  87. }
  88. static u32 GetDepth(int x, int y) {
  89. const auto& framebuffer = g_state.regs.framebuffer;
  90. const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
  91. u8* depth_buffer = Memory::GetPhysicalPointer(addr);
  92. y = framebuffer.height - y;
  93. const u32 coarse_y = y & ~7;
  94. u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format);
  95. u32 stride = framebuffer.width * bytes_per_pixel;
  96. u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
  97. u8* src_pixel = depth_buffer + src_offset;
  98. switch (framebuffer.depth_format) {
  99. case Regs::DepthFormat::D16:
  100. return Color::DecodeD16(src_pixel);
  101. case Regs::DepthFormat::D24:
  102. return Color::DecodeD24(src_pixel);
  103. case Regs::DepthFormat::D24S8:
  104. return Color::DecodeD24S8(src_pixel).x;
  105. default:
  106. LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format);
  107. UNIMPLEMENTED();
  108. return 0;
  109. }
  110. }
  111. static u8 GetStencil(int x, int y) {
  112. const auto& framebuffer = g_state.regs.framebuffer;
  113. const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
  114. u8* depth_buffer = Memory::GetPhysicalPointer(addr);
  115. y = framebuffer.height - y;
  116. const u32 coarse_y = y & ~7;
  117. u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(framebuffer.depth_format);
  118. u32 stride = framebuffer.width * bytes_per_pixel;
  119. u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
  120. u8* src_pixel = depth_buffer + src_offset;
  121. switch (framebuffer.depth_format) {
  122. case Regs::DepthFormat::D24S8:
  123. return Color::DecodeD24S8(src_pixel).y;
  124. default:
  125. LOG_WARNING(
  126. HW_GPU,
  127. "GetStencil called for function which doesn't have a stencil component (format %u)",
  128. framebuffer.depth_format);
  129. return 0;
  130. }
  131. }
  132. static void SetDepth(int x, int y, u32 value) {
  133. const auto& framebuffer = g_state.regs.framebuffer;
  134. const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
  135. u8* depth_buffer = Memory::GetPhysicalPointer(addr);
  136. y = framebuffer.height - y;
  137. const u32 coarse_y = y & ~7;
  138. u32 bytes_per_pixel = Regs::BytesPerDepthPixel(framebuffer.depth_format);
  139. u32 stride = framebuffer.width * bytes_per_pixel;
  140. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
  141. u8* dst_pixel = depth_buffer + dst_offset;
  142. switch (framebuffer.depth_format) {
  143. case Regs::DepthFormat::D16:
  144. Color::EncodeD16(value, dst_pixel);
  145. break;
  146. case Regs::DepthFormat::D24:
  147. Color::EncodeD24(value, dst_pixel);
  148. break;
  149. case Regs::DepthFormat::D24S8:
  150. Color::EncodeD24X8(value, dst_pixel);
  151. break;
  152. default:
  153. LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format);
  154. UNIMPLEMENTED();
  155. break;
  156. }
  157. }
  158. static void SetStencil(int x, int y, u8 value) {
  159. const auto& framebuffer = g_state.regs.framebuffer;
  160. const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress();
  161. u8* depth_buffer = Memory::GetPhysicalPointer(addr);
  162. y = framebuffer.height - y;
  163. const u32 coarse_y = y & ~7;
  164. u32 bytes_per_pixel = Pica::Regs::BytesPerDepthPixel(framebuffer.depth_format);
  165. u32 stride = framebuffer.width * bytes_per_pixel;
  166. u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
  167. u8* dst_pixel = depth_buffer + dst_offset;
  168. switch (framebuffer.depth_format) {
  169. case Pica::Regs::DepthFormat::D16:
  170. case Pica::Regs::DepthFormat::D24:
  171. // Nothing to do
  172. break;
  173. case Pica::Regs::DepthFormat::D24S8:
  174. Color::EncodeX24S8(value, dst_pixel);
  175. break;
  176. default:
  177. LOG_CRITICAL(HW_GPU, "Unimplemented depth format %u", framebuffer.depth_format);
  178. UNIMPLEMENTED();
  179. break;
  180. }
  181. }
  182. static u8 PerformStencilAction(Regs::StencilAction action, u8 old_stencil, u8 ref) {
  183. switch (action) {
  184. case Regs::StencilAction::Keep:
  185. return old_stencil;
  186. case Regs::StencilAction::Zero:
  187. return 0;
  188. case Regs::StencilAction::Replace:
  189. return ref;
  190. case Regs::StencilAction::Increment:
  191. // Saturated increment
  192. return std::min<u8>(old_stencil, 254) + 1;
  193. case Regs::StencilAction::Decrement:
  194. // Saturated decrement
  195. return std::max<u8>(old_stencil, 1) - 1;
  196. case Regs::StencilAction::Invert:
  197. return ~old_stencil;
  198. case Regs::StencilAction::IncrementWrap:
  199. return old_stencil + 1;
  200. case Regs::StencilAction::DecrementWrap:
  201. return old_stencil - 1;
  202. default:
  203. LOG_CRITICAL(HW_GPU, "Unknown stencil action %x", (int)action);
  204. UNIMPLEMENTED();
  205. return 0;
  206. }
  207. }
  208. // NOTE: Assuming that rasterizer coordinates are 12.4 fixed-point values
  209. struct Fix12P4 {
  210. Fix12P4() {}
  211. Fix12P4(u16 val) : val(val) {}
  212. static u16 FracMask() {
  213. return 0xF;
  214. }
  215. static u16 IntMask() {
  216. return (u16)~0xF;
  217. }
  218. operator u16() const {
  219. return val;
  220. }
  221. bool operator<(const Fix12P4& oth) const {
  222. return (u16) * this < (u16)oth;
  223. }
  224. private:
  225. u16 val;
  226. };
  227. /**
  228. * Calculate signed area of the triangle spanned by the three argument vertices.
  229. * The sign denotes an orientation.
  230. *
  231. * @todo define orientation concretely.
  232. */
  233. static int SignedArea(const Math::Vec2<Fix12P4>& vtx1, const Math::Vec2<Fix12P4>& vtx2,
  234. const Math::Vec2<Fix12P4>& vtx3) {
  235. const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0);
  236. const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0);
  237. // TODO: There is a very small chance this will overflow for sizeof(int) == 4
  238. return Math::Cross(vec1, vec2).z;
  239. };
  240. MICROPROFILE_DEFINE(GPU_Rasterization, "GPU", "Rasterization", MP_RGB(50, 50, 240));
  241. /**
  242. * Helper function for ProcessTriangle with the "reversed" flag to allow for implementing
  243. * culling via recursion.
  244. */
  245. static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Vertex& v2,
  246. bool reversed = false) {
  247. const auto& regs = g_state.regs;
  248. MICROPROFILE_SCOPE(GPU_Rasterization);
  249. // vertex positions in rasterizer coordinates
  250. static auto FloatToFix = [](float24 flt) {
  251. // TODO: Rounding here is necessary to prevent garbage pixels at
  252. // triangle borders. Is it that the correct solution, though?
  253. return Fix12P4(static_cast<unsigned short>(round(flt.ToFloat32() * 16.0f)));
  254. };
  255. static auto ScreenToRasterizerCoordinates = [](const Math::Vec3<float24>& vec) {
  256. return Math::Vec3<Fix12P4>{FloatToFix(vec.x), FloatToFix(vec.y), FloatToFix(vec.z)};
  257. };
  258. Math::Vec3<Fix12P4> vtxpos[3]{ScreenToRasterizerCoordinates(v0.screenpos),
  259. ScreenToRasterizerCoordinates(v1.screenpos),
  260. ScreenToRasterizerCoordinates(v2.screenpos)};
  261. if (regs.cull_mode == Regs::CullMode::KeepAll) {
  262. // Make sure we always end up with a triangle wound counter-clockwise
  263. if (!reversed && SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) {
  264. ProcessTriangleInternal(v0, v2, v1, true);
  265. return;
  266. }
  267. } else {
  268. if (!reversed && regs.cull_mode == Regs::CullMode::KeepClockWise) {
  269. // Reverse vertex order and use the CCW code path.
  270. ProcessTriangleInternal(v0, v2, v1, true);
  271. return;
  272. }
  273. // Cull away triangles which are wound clockwise.
  274. if (SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0)
  275. return;
  276. }
  277. u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
  278. u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
  279. u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
  280. u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
  281. // Convert the scissor box coordinates to 12.4 fixed point
  282. u16 scissor_x1 = (u16)(regs.scissor_test.x1 << 4);
  283. u16 scissor_y1 = (u16)(regs.scissor_test.y1 << 4);
  284. // x2,y2 have +1 added to cover the entire sub-pixel area
  285. u16 scissor_x2 = (u16)((regs.scissor_test.x2 + 1) << 4);
  286. u16 scissor_y2 = (u16)((regs.scissor_test.y2 + 1) << 4);
  287. if (regs.scissor_test.mode == Regs::ScissorMode::Include) {
  288. // Calculate the new bounds
  289. min_x = std::max(min_x, scissor_x1);
  290. min_y = std::max(min_y, scissor_y1);
  291. max_x = std::min(max_x, scissor_x2);
  292. max_y = std::min(max_y, scissor_y2);
  293. }
  294. min_x &= Fix12P4::IntMask();
  295. min_y &= Fix12P4::IntMask();
  296. max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask());
  297. max_y = ((max_y + Fix12P4::FracMask()) & Fix12P4::IntMask());
  298. // Triangle filling rules: Pixels on the right-sided edge or on flat bottom edges are not
  299. // drawn. Pixels on any other triangle border are drawn. This is implemented with three bias
  300. // values which are added to the barycentric coordinates w0, w1 and w2, respectively.
  301. // NOTE: These are the PSP filling rules. Not sure if the 3DS uses the same ones...
  302. auto IsRightSideOrFlatBottomEdge = [](const Math::Vec2<Fix12P4>& vtx,
  303. const Math::Vec2<Fix12P4>& line1,
  304. const Math::Vec2<Fix12P4>& line2) {
  305. if (line1.y == line2.y) {
  306. // just check if vertex is above us => bottom line parallel to x-axis
  307. return vtx.y < line1.y;
  308. } else {
  309. // check if vertex is on our left => right side
  310. // TODO: Not sure how likely this is to overflow
  311. return (int)vtx.x < (int)line1.x +
  312. ((int)line2.x - (int)line1.x) * ((int)vtx.y - (int)line1.y) /
  313. ((int)line2.y - (int)line1.y);
  314. }
  315. };
  316. int bias0 =
  317. IsRightSideOrFlatBottomEdge(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) ? -1 : 0;
  318. int bias1 =
  319. IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0;
  320. int bias2 =
  321. IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0;
  322. auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
  323. auto textures = regs.GetTextures();
  324. auto tev_stages = regs.GetTevStages();
  325. bool stencil_action_enable = g_state.regs.output_merger.stencil_test.enable &&
  326. g_state.regs.framebuffer.depth_format == Regs::DepthFormat::D24S8;
  327. const auto stencil_test = g_state.regs.output_merger.stencil_test;
  328. // Enter rasterization loop, starting at the center of the topleft bounding box corner.
  329. // TODO: Not sure if looping through x first might be faster
  330. for (u16 y = min_y + 8; y < max_y; y += 0x10) {
  331. for (u16 x = min_x + 8; x < max_x; x += 0x10) {
  332. // Do not process the pixel if it's inside the scissor box and the scissor mode is set
  333. // to Exclude
  334. if (regs.scissor_test.mode == Regs::ScissorMode::Exclude) {
  335. if (x >= scissor_x1 && x < scissor_x2 && y >= scissor_y1 && y < scissor_y2)
  336. continue;
  337. }
  338. // Calculate the barycentric coordinates w0, w1 and w2
  339. int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y});
  340. int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y});
  341. int w2 = bias2 + SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), {x, y});
  342. int wsum = w0 + w1 + w2;
  343. // If current pixel is not covered by the current primitive
  344. if (w0 < 0 || w1 < 0 || w2 < 0)
  345. continue;
  346. auto baricentric_coordinates =
  347. Math::MakeVec(float24::FromFloat32(static_cast<float>(w0)),
  348. float24::FromFloat32(static_cast<float>(w1)),
  349. float24::FromFloat32(static_cast<float>(w2)));
  350. float24 interpolated_w_inverse =
  351. float24::FromFloat32(1.0f) / Math::Dot(w_inverse, baricentric_coordinates);
  352. // interpolated_z = z / w
  353. float interpolated_z_over_w =
  354. (v0.screenpos[2].ToFloat32() * w0 + v1.screenpos[2].ToFloat32() * w1 +
  355. v2.screenpos[2].ToFloat32() * w2) /
  356. wsum;
  357. // Not fully accurate. About 3 bits in precision are missing.
  358. // Z-Buffer (z / w * scale + offset)
  359. float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32();
  360. float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32();
  361. float depth = interpolated_z_over_w * depth_scale + depth_offset;
  362. // Potentially switch to W-Buffer
  363. if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
  364. // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w)
  365. depth *= interpolated_w_inverse.ToFloat32() * wsum;
  366. }
  367. // Clamp the result
  368. depth = MathUtil::Clamp(depth, 0.0f, 1.0f);
  369. // Perspective correct attribute interpolation:
  370. // Attribute values cannot be calculated by simple linear interpolation since
  371. // they are not linear in screen space. For example, when interpolating a
  372. // texture coordinate across two vertices, something simple like
  373. // u = (u0*w0 + u1*w1)/(w0+w1)
  374. // will not work. However, the attribute value divided by the
  375. // clipspace w-coordinate (u/w) and and the inverse w-coordinate (1/w) are linear
  376. // in screenspace. Hence, we can linearly interpolate these two independently and
  377. // calculate the interpolated attribute by dividing the results.
  378. // I.e.
  379. // u_over_w = ((u0/v0.pos.w)*w0 + (u1/v1.pos.w)*w1)/(w0+w1)
  380. // one_over_w = (( 1/v0.pos.w)*w0 + ( 1/v1.pos.w)*w1)/(w0+w1)
  381. // u = u_over_w / one_over_w
  382. //
  383. // The generalization to three vertices is straightforward in baricentric coordinates.
  384. auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) {
  385. auto attr_over_w = Math::MakeVec(attr0, attr1, attr2);
  386. float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates);
  387. return interpolated_attr_over_w * interpolated_w_inverse;
  388. };
  389. Math::Vec4<u8> primary_color{
  390. (u8)(
  391. GetInterpolatedAttribute(v0.color.r(), v1.color.r(), v2.color.r()).ToFloat32() *
  392. 255),
  393. (u8)(
  394. GetInterpolatedAttribute(v0.color.g(), v1.color.g(), v2.color.g()).ToFloat32() *
  395. 255),
  396. (u8)(
  397. GetInterpolatedAttribute(v0.color.b(), v1.color.b(), v2.color.b()).ToFloat32() *
  398. 255),
  399. (u8)(
  400. GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() *
  401. 255),
  402. };
  403. Math::Vec2<float24> uv[3];
  404. uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u());
  405. uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v());
  406. uv[1].u() = GetInterpolatedAttribute(v0.tc1.u(), v1.tc1.u(), v2.tc1.u());
  407. uv[1].v() = GetInterpolatedAttribute(v0.tc1.v(), v1.tc1.v(), v2.tc1.v());
  408. uv[2].u() = GetInterpolatedAttribute(v0.tc2.u(), v1.tc2.u(), v2.tc2.u());
  409. uv[2].v() = GetInterpolatedAttribute(v0.tc2.v(), v1.tc2.v(), v2.tc2.v());
  410. Math::Vec4<u8> texture_color[3]{};
  411. for (int i = 0; i < 3; ++i) {
  412. const auto& texture = textures[i];
  413. if (!texture.enabled)
  414. continue;
  415. DEBUG_ASSERT(0 != texture.config.address);
  416. float24 u = uv[i].u();
  417. float24 v = uv[i].v();
  418. // Only unit 0 respects the texturing type (according to 3DBrew)
  419. // TODO: Refactor so cubemaps and shadowmaps can be handled
  420. if (i == 0) {
  421. switch (texture.config.type) {
  422. case Regs::TextureConfig::Texture2D:
  423. break;
  424. case Regs::TextureConfig::Projection2D: {
  425. auto tc0_w = GetInterpolatedAttribute(v0.tc0_w, v1.tc0_w, v2.tc0_w);
  426. u /= tc0_w;
  427. v /= tc0_w;
  428. break;
  429. }
  430. default:
  431. // TODO: Change to LOG_ERROR when more types are handled.
  432. LOG_DEBUG(HW_GPU, "Unhandled texture type %x", (int)texture.config.type);
  433. UNIMPLEMENTED();
  434. break;
  435. }
  436. }
  437. int s = (int)(u * float24::FromFloat32(static_cast<float>(texture.config.width)))
  438. .ToFloat32();
  439. int t = (int)(v * float24::FromFloat32(static_cast<float>(texture.config.height)))
  440. .ToFloat32();
  441. static auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val,
  442. unsigned size) {
  443. switch (mode) {
  444. case Regs::TextureConfig::ClampToEdge:
  445. val = std::max(val, 0);
  446. val = std::min(val, (int)size - 1);
  447. return val;
  448. case Regs::TextureConfig::ClampToBorder:
  449. return val;
  450. case Regs::TextureConfig::Repeat:
  451. return (int)((unsigned)val % size);
  452. case Regs::TextureConfig::MirroredRepeat: {
  453. unsigned int coord = ((unsigned)val % (2 * size));
  454. if (coord >= size)
  455. coord = 2 * size - 1 - coord;
  456. return (int)coord;
  457. }
  458. default:
  459. LOG_ERROR(HW_GPU, "Unknown texture coordinate wrapping mode %x", (int)mode);
  460. UNIMPLEMENTED();
  461. return 0;
  462. }
  463. };
  464. if ((texture.config.wrap_s == Regs::TextureConfig::ClampToBorder &&
  465. (s < 0 || static_cast<u32>(s) >= texture.config.width)) ||
  466. (texture.config.wrap_t == Regs::TextureConfig::ClampToBorder &&
  467. (t < 0 || static_cast<u32>(t) >= texture.config.height))) {
  468. auto border_color = texture.config.border_color;
  469. texture_color[i] = {border_color.r, border_color.g, border_color.b,
  470. border_color.a};
  471. } else {
  472. // Textures are laid out from bottom to top, hence we invert the t coordinate.
  473. // NOTE: This may not be the right place for the inversion.
  474. // TODO: Check if this applies to ETC textures, too.
  475. s = GetWrappedTexCoord(texture.config.wrap_s, s, texture.config.width);
  476. t = texture.config.height - 1 -
  477. GetWrappedTexCoord(texture.config.wrap_t, t, texture.config.height);
  478. u8* texture_data =
  479. Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress());
  480. auto info =
  481. DebugUtils::TextureInfo::FromPicaRegister(texture.config, texture.format);
  482. // TODO: Apply the min and mag filters to the texture
  483. texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info);
  484. #if PICA_DUMP_TEXTURES
  485. DebugUtils::DumpTexture(texture.config, texture_data);
  486. #endif
  487. }
  488. }
  489. // Texture environment - consists of 6 stages of color and alpha combining.
  490. //
  491. // Color combiners take three input color values from some source (e.g. interpolated
  492. // vertex color, texture color, previous stage, etc), perform some very simple
  493. // operations on each of them (e.g. inversion) and then calculate the output color
  494. // with some basic arithmetic. Alpha combiners can be configured separately but work
  495. // analogously.
  496. Math::Vec4<u8> combiner_output;
  497. Math::Vec4<u8> combiner_buffer = {0, 0, 0, 0};
  498. Math::Vec4<u8> next_combiner_buffer = {
  499. regs.tev_combiner_buffer_color.r, regs.tev_combiner_buffer_color.g,
  500. regs.tev_combiner_buffer_color.b, regs.tev_combiner_buffer_color.a,
  501. };
  502. for (unsigned tev_stage_index = 0; tev_stage_index < tev_stages.size();
  503. ++tev_stage_index) {
  504. const auto& tev_stage = tev_stages[tev_stage_index];
  505. using Source = Regs::TevStageConfig::Source;
  506. using ColorModifier = Regs::TevStageConfig::ColorModifier;
  507. using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
  508. using Operation = Regs::TevStageConfig::Operation;
  509. auto GetSource = [&](Source source) -> Math::Vec4<u8> {
  510. switch (source) {
  511. case Source::PrimaryColor:
  512. // HACK: Until we implement fragment lighting, use primary_color
  513. case Source::PrimaryFragmentColor:
  514. return primary_color;
  515. // HACK: Until we implement fragment lighting, use zero
  516. case Source::SecondaryFragmentColor:
  517. return {0, 0, 0, 0};
  518. case Source::Texture0:
  519. return texture_color[0];
  520. case Source::Texture1:
  521. return texture_color[1];
  522. case Source::Texture2:
  523. return texture_color[2];
  524. case Source::PreviousBuffer:
  525. return combiner_buffer;
  526. case Source::Constant:
  527. return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b,
  528. tev_stage.const_a};
  529. case Source::Previous:
  530. return combiner_output;
  531. default:
  532. LOG_ERROR(HW_GPU, "Unknown color combiner source %d", (int)source);
  533. UNIMPLEMENTED();
  534. return {0, 0, 0, 0};
  535. }
  536. };
  537. static auto GetColorModifier = [](ColorModifier factor,
  538. const Math::Vec4<u8>& values) -> Math::Vec3<u8> {
  539. switch (factor) {
  540. case ColorModifier::SourceColor:
  541. return values.rgb();
  542. case ColorModifier::OneMinusSourceColor:
  543. return (Math::Vec3<u8>(255, 255, 255) - values.rgb()).Cast<u8>();
  544. case ColorModifier::SourceAlpha:
  545. return values.aaa();
  546. case ColorModifier::OneMinusSourceAlpha:
  547. return (Math::Vec3<u8>(255, 255, 255) - values.aaa()).Cast<u8>();
  548. case ColorModifier::SourceRed:
  549. return values.rrr();
  550. case ColorModifier::OneMinusSourceRed:
  551. return (Math::Vec3<u8>(255, 255, 255) - values.rrr()).Cast<u8>();
  552. case ColorModifier::SourceGreen:
  553. return values.ggg();
  554. case ColorModifier::OneMinusSourceGreen:
  555. return (Math::Vec3<u8>(255, 255, 255) - values.ggg()).Cast<u8>();
  556. case ColorModifier::SourceBlue:
  557. return values.bbb();
  558. case ColorModifier::OneMinusSourceBlue:
  559. return (Math::Vec3<u8>(255, 255, 255) - values.bbb()).Cast<u8>();
  560. }
  561. };
  562. static auto GetAlphaModifier = [](AlphaModifier factor,
  563. const Math::Vec4<u8>& values) -> u8 {
  564. switch (factor) {
  565. case AlphaModifier::SourceAlpha:
  566. return values.a();
  567. case AlphaModifier::OneMinusSourceAlpha:
  568. return 255 - values.a();
  569. case AlphaModifier::SourceRed:
  570. return values.r();
  571. case AlphaModifier::OneMinusSourceRed:
  572. return 255 - values.r();
  573. case AlphaModifier::SourceGreen:
  574. return values.g();
  575. case AlphaModifier::OneMinusSourceGreen:
  576. return 255 - values.g();
  577. case AlphaModifier::SourceBlue:
  578. return values.b();
  579. case AlphaModifier::OneMinusSourceBlue:
  580. return 255 - values.b();
  581. }
  582. };
  583. static auto ColorCombine = [](Operation op,
  584. const Math::Vec3<u8> input[3]) -> Math::Vec3<u8> {
  585. switch (op) {
  586. case Operation::Replace:
  587. return input[0];
  588. case Operation::Modulate:
  589. return ((input[0] * input[1]) / 255).Cast<u8>();
  590. case Operation::Add: {
  591. auto result = input[0] + input[1];
  592. result.r() = std::min(255, result.r());
  593. result.g() = std::min(255, result.g());
  594. result.b() = std::min(255, result.b());
  595. return result.Cast<u8>();
  596. }
  597. case Operation::AddSigned: {
  598. // TODO(bunnei): Verify that the color conversion from (float) 0.5f to
  599. // (byte) 128 is correct
  600. auto result = input[0].Cast<int>() + input[1].Cast<int>() -
  601. Math::MakeVec<int>(128, 128, 128);
  602. result.r() = MathUtil::Clamp<int>(result.r(), 0, 255);
  603. result.g() = MathUtil::Clamp<int>(result.g(), 0, 255);
  604. result.b() = MathUtil::Clamp<int>(result.b(), 0, 255);
  605. return result.Cast<u8>();
  606. }
  607. case Operation::Lerp:
  608. return ((input[0] * input[2] +
  609. input[1] *
  610. (Math::MakeVec<u8>(255, 255, 255) - input[2]).Cast<u8>()) /
  611. 255)
  612. .Cast<u8>();
  613. case Operation::Subtract: {
  614. auto result = input[0].Cast<int>() - input[1].Cast<int>();
  615. result.r() = std::max(0, result.r());
  616. result.g() = std::max(0, result.g());
  617. result.b() = std::max(0, result.b());
  618. return result.Cast<u8>();
  619. }
  620. case Operation::MultiplyThenAdd: {
  621. auto result = (input[0] * input[1] + 255 * input[2].Cast<int>()) / 255;
  622. result.r() = std::min(255, result.r());
  623. result.g() = std::min(255, result.g());
  624. result.b() = std::min(255, result.b());
  625. return result.Cast<u8>();
  626. }
  627. case Operation::AddThenMultiply: {
  628. auto result = input[0] + input[1];
  629. result.r() = std::min(255, result.r());
  630. result.g() = std::min(255, result.g());
  631. result.b() = std::min(255, result.b());
  632. result = (result * input[2].Cast<int>()) / 255;
  633. return result.Cast<u8>();
  634. }
  635. case Operation::Dot3_RGB: {
  636. // Not fully accurate.
  637. // Worst case scenario seems to yield a +/-3 error
  638. // Some HW results indicate that the per-component computation can't have a
  639. // higher precision than 1/256,
  640. // while dot3_rgb( (0x80,g0,b0),(0x7F,g1,b1) ) and dot3_rgb(
  641. // (0x80,g0,b0),(0x80,g1,b1) ) give different results
  642. int result =
  643. ((input[0].r() * 2 - 255) * (input[1].r() * 2 - 255) + 128) / 256 +
  644. ((input[0].g() * 2 - 255) * (input[1].g() * 2 - 255) + 128) / 256 +
  645. ((input[0].b() * 2 - 255) * (input[1].b() * 2 - 255) + 128) / 256;
  646. result = std::max(0, std::min(255, result));
  647. return {(u8)result, (u8)result, (u8)result};
  648. }
  649. default:
  650. LOG_ERROR(HW_GPU, "Unknown color combiner operation %d", (int)op);
  651. UNIMPLEMENTED();
  652. return {0, 0, 0};
  653. }
  654. };
  655. static auto AlphaCombine = [](Operation op, const std::array<u8, 3>& input) -> u8 {
  656. switch (op) {
  657. case Operation::Replace:
  658. return input[0];
  659. case Operation::Modulate:
  660. return input[0] * input[1] / 255;
  661. case Operation::Add:
  662. return std::min(255, input[0] + input[1]);
  663. case Operation::AddSigned: {
  664. // TODO(bunnei): Verify that the color conversion from (float) 0.5f to
  665. // (byte) 128 is correct
  666. auto result = static_cast<int>(input[0]) + static_cast<int>(input[1]) - 128;
  667. return static_cast<u8>(MathUtil::Clamp<int>(result, 0, 255));
  668. }
  669. case Operation::Lerp:
  670. return (input[0] * input[2] + input[1] * (255 - input[2])) / 255;
  671. case Operation::Subtract:
  672. return std::max(0, (int)input[0] - (int)input[1]);
  673. case Operation::MultiplyThenAdd:
  674. return std::min(255, (input[0] * input[1] + 255 * input[2]) / 255);
  675. case Operation::AddThenMultiply:
  676. return (std::min(255, (input[0] + input[1])) * input[2]) / 255;
  677. default:
  678. LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d", (int)op);
  679. UNIMPLEMENTED();
  680. return 0;
  681. }
  682. };
  683. // color combiner
  684. // NOTE: Not sure if the alpha combiner might use the color output of the previous
  685. // stage as input. Hence, we currently don't directly write the result to
  686. // combiner_output.rgb(), but instead store it in a temporary variable until
  687. // alpha combining has been done.
  688. Math::Vec3<u8> color_result[3] = {
  689. GetColorModifier(tev_stage.color_modifier1, GetSource(tev_stage.color_source1)),
  690. GetColorModifier(tev_stage.color_modifier2, GetSource(tev_stage.color_source2)),
  691. GetColorModifier(tev_stage.color_modifier3, GetSource(tev_stage.color_source3)),
  692. };
  693. auto color_output = ColorCombine(tev_stage.color_op, color_result);
  694. // alpha combiner
  695. std::array<u8, 3> alpha_result = {{
  696. GetAlphaModifier(tev_stage.alpha_modifier1, GetSource(tev_stage.alpha_source1)),
  697. GetAlphaModifier(tev_stage.alpha_modifier2, GetSource(tev_stage.alpha_source2)),
  698. GetAlphaModifier(tev_stage.alpha_modifier3, GetSource(tev_stage.alpha_source3)),
  699. }};
  700. auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result);
  701. combiner_output[0] =
  702. std::min((unsigned)255, color_output.r() * tev_stage.GetColorMultiplier());
  703. combiner_output[1] =
  704. std::min((unsigned)255, color_output.g() * tev_stage.GetColorMultiplier());
  705. combiner_output[2] =
  706. std::min((unsigned)255, color_output.b() * tev_stage.GetColorMultiplier());
  707. combiner_output[3] =
  708. std::min((unsigned)255, alpha_output * tev_stage.GetAlphaMultiplier());
  709. combiner_buffer = next_combiner_buffer;
  710. if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferColor(
  711. tev_stage_index)) {
  712. next_combiner_buffer.r() = combiner_output.r();
  713. next_combiner_buffer.g() = combiner_output.g();
  714. next_combiner_buffer.b() = combiner_output.b();
  715. }
  716. if (regs.tev_combiner_buffer_input.TevStageUpdatesCombinerBufferAlpha(
  717. tev_stage_index)) {
  718. next_combiner_buffer.a() = combiner_output.a();
  719. }
  720. }
  721. const auto& output_merger = regs.output_merger;
  722. // TODO: Does alpha testing happen before or after stencil?
  723. if (output_merger.alpha_test.enable) {
  724. bool pass = false;
  725. switch (output_merger.alpha_test.func) {
  726. case Regs::CompareFunc::Never:
  727. pass = false;
  728. break;
  729. case Regs::CompareFunc::Always:
  730. pass = true;
  731. break;
  732. case Regs::CompareFunc::Equal:
  733. pass = combiner_output.a() == output_merger.alpha_test.ref;
  734. break;
  735. case Regs::CompareFunc::NotEqual:
  736. pass = combiner_output.a() != output_merger.alpha_test.ref;
  737. break;
  738. case Regs::CompareFunc::LessThan:
  739. pass = combiner_output.a() < output_merger.alpha_test.ref;
  740. break;
  741. case Regs::CompareFunc::LessThanOrEqual:
  742. pass = combiner_output.a() <= output_merger.alpha_test.ref;
  743. break;
  744. case Regs::CompareFunc::GreaterThan:
  745. pass = combiner_output.a() > output_merger.alpha_test.ref;
  746. break;
  747. case Regs::CompareFunc::GreaterThanOrEqual:
  748. pass = combiner_output.a() >= output_merger.alpha_test.ref;
  749. break;
  750. }
  751. if (!pass)
  752. continue;
  753. }
  754. // Apply fog combiner
  755. // Not fully accurate. We'd have to know what data type is used to
  756. // store the depth etc. Using float for now until we know more
  757. // about Pica datatypes
  758. if (regs.fog_mode == Regs::FogMode::Fog) {
  759. const Math::Vec3<u8> fog_color = {
  760. static_cast<u8>(regs.fog_color.r.Value()),
  761. static_cast<u8>(regs.fog_color.g.Value()),
  762. static_cast<u8>(regs.fog_color.b.Value()),
  763. };
  764. // Get index into fog LUT
  765. float fog_index;
  766. if (g_state.regs.fog_flip) {
  767. fog_index = (1.0f - depth) * 128.0f;
  768. } else {
  769. fog_index = depth * 128.0f;
  770. }
  771. // Generate clamped fog factor from LUT for given fog index
  772. float fog_i = MathUtil::Clamp(floorf(fog_index), 0.0f, 127.0f);
  773. float fog_f = fog_index - fog_i;
  774. const auto& fog_lut_entry = g_state.fog.lut[static_cast<unsigned int>(fog_i)];
  775. float fog_factor = (fog_lut_entry.value + fog_lut_entry.difference * fog_f) /
  776. 2047.0f; // This is signed fixed point 1.11
  777. fog_factor = MathUtil::Clamp(fog_factor, 0.0f, 1.0f);
  778. // Blend the fog
  779. for (unsigned i = 0; i < 3; i++) {
  780. combiner_output[i] = static_cast<u8>(fog_factor * combiner_output[i] +
  781. (1.0f - fog_factor) * fog_color[i]);
  782. }
  783. }
  784. u8 old_stencil = 0;
  785. auto UpdateStencil = [stencil_test, x, y,
  786. &old_stencil](Pica::Regs::StencilAction action) {
  787. u8 new_stencil =
  788. PerformStencilAction(action, old_stencil, stencil_test.reference_value);
  789. if (g_state.regs.framebuffer.allow_depth_stencil_write != 0)
  790. SetStencil(x >> 4, y >> 4, (new_stencil & stencil_test.write_mask) |
  791. (old_stencil & ~stencil_test.write_mask));
  792. };
  793. if (stencil_action_enable) {
  794. old_stencil = GetStencil(x >> 4, y >> 4);
  795. u8 dest = old_stencil & stencil_test.input_mask;
  796. u8 ref = stencil_test.reference_value & stencil_test.input_mask;
  797. bool pass = false;
  798. switch (stencil_test.func) {
  799. case Regs::CompareFunc::Never:
  800. pass = false;
  801. break;
  802. case Regs::CompareFunc::Always:
  803. pass = true;
  804. break;
  805. case Regs::CompareFunc::Equal:
  806. pass = (ref == dest);
  807. break;
  808. case Regs::CompareFunc::NotEqual:
  809. pass = (ref != dest);
  810. break;
  811. case Regs::CompareFunc::LessThan:
  812. pass = (ref < dest);
  813. break;
  814. case Regs::CompareFunc::LessThanOrEqual:
  815. pass = (ref <= dest);
  816. break;
  817. case Regs::CompareFunc::GreaterThan:
  818. pass = (ref > dest);
  819. break;
  820. case Regs::CompareFunc::GreaterThanOrEqual:
  821. pass = (ref >= dest);
  822. break;
  823. }
  824. if (!pass) {
  825. UpdateStencil(stencil_test.action_stencil_fail);
  826. continue;
  827. }
  828. }
  829. // Convert float to integer
  830. unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format);
  831. u32 z = (u32)(depth * ((1 << num_bits) - 1));
  832. if (output_merger.depth_test_enable) {
  833. u32 ref_z = GetDepth(x >> 4, y >> 4);
  834. bool pass = false;
  835. switch (output_merger.depth_test_func) {
  836. case Regs::CompareFunc::Never:
  837. pass = false;
  838. break;
  839. case Regs::CompareFunc::Always:
  840. pass = true;
  841. break;
  842. case Regs::CompareFunc::Equal:
  843. pass = z == ref_z;
  844. break;
  845. case Regs::CompareFunc::NotEqual:
  846. pass = z != ref_z;
  847. break;
  848. case Regs::CompareFunc::LessThan:
  849. pass = z < ref_z;
  850. break;
  851. case Regs::CompareFunc::LessThanOrEqual:
  852. pass = z <= ref_z;
  853. break;
  854. case Regs::CompareFunc::GreaterThan:
  855. pass = z > ref_z;
  856. break;
  857. case Regs::CompareFunc::GreaterThanOrEqual:
  858. pass = z >= ref_z;
  859. break;
  860. }
  861. if (!pass) {
  862. if (stencil_action_enable)
  863. UpdateStencil(stencil_test.action_depth_fail);
  864. continue;
  865. }
  866. }
  867. if (regs.framebuffer.allow_depth_stencil_write != 0 && output_merger.depth_write_enable)
  868. SetDepth(x >> 4, y >> 4, z);
  869. // The stencil depth_pass action is executed even if depth testing is disabled
  870. if (stencil_action_enable)
  871. UpdateStencil(stencil_test.action_depth_pass);
  872. auto dest = GetPixel(x >> 4, y >> 4);
  873. Math::Vec4<u8> blend_output = combiner_output;
  874. if (output_merger.alphablend_enable) {
  875. auto params = output_merger.alpha_blending;
  876. auto LookupFactor = [&](unsigned channel, Regs::BlendFactor factor) -> u8 {
  877. DEBUG_ASSERT(channel < 4);
  878. const Math::Vec4<u8> blend_const = {
  879. static_cast<u8>(output_merger.blend_const.r),
  880. static_cast<u8>(output_merger.blend_const.g),
  881. static_cast<u8>(output_merger.blend_const.b),
  882. static_cast<u8>(output_merger.blend_const.a),
  883. };
  884. switch (factor) {
  885. case Regs::BlendFactor::Zero:
  886. return 0;
  887. case Regs::BlendFactor::One:
  888. return 255;
  889. case Regs::BlendFactor::SourceColor:
  890. return combiner_output[channel];
  891. case Regs::BlendFactor::OneMinusSourceColor:
  892. return 255 - combiner_output[channel];
  893. case Regs::BlendFactor::DestColor:
  894. return dest[channel];
  895. case Regs::BlendFactor::OneMinusDestColor:
  896. return 255 - dest[channel];
  897. case Regs::BlendFactor::SourceAlpha:
  898. return combiner_output.a();
  899. case Regs::BlendFactor::OneMinusSourceAlpha:
  900. return 255 - combiner_output.a();
  901. case Regs::BlendFactor::DestAlpha:
  902. return dest.a();
  903. case Regs::BlendFactor::OneMinusDestAlpha:
  904. return 255 - dest.a();
  905. case Regs::BlendFactor::ConstantColor:
  906. return blend_const[channel];
  907. case Regs::BlendFactor::OneMinusConstantColor:
  908. return 255 - blend_const[channel];
  909. case Regs::BlendFactor::ConstantAlpha:
  910. return blend_const.a();
  911. case Regs::BlendFactor::OneMinusConstantAlpha:
  912. return 255 - blend_const.a();
  913. case Regs::BlendFactor::SourceAlphaSaturate:
  914. // Returns 1.0 for the alpha channel
  915. if (channel == 3)
  916. return 255;
  917. return std::min(combiner_output.a(), static_cast<u8>(255 - dest.a()));
  918. default:
  919. LOG_CRITICAL(HW_GPU, "Unknown blend factor %x", factor);
  920. UNIMPLEMENTED();
  921. break;
  922. }
  923. return combiner_output[channel];
  924. };
  925. static auto EvaluateBlendEquation = [](
  926. const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor,
  927. const Math::Vec4<u8>& dest, const Math::Vec4<u8>& destfactor,
  928. Regs::BlendEquation equation) {
  929. Math::Vec4<int> result;
  930. auto src_result = (src * srcfactor).Cast<int>();
  931. auto dst_result = (dest * destfactor).Cast<int>();
  932. switch (equation) {
  933. case Regs::BlendEquation::Add:
  934. result = (src_result + dst_result) / 255;
  935. break;
  936. case Regs::BlendEquation::Subtract:
  937. result = (src_result - dst_result) / 255;
  938. break;
  939. case Regs::BlendEquation::ReverseSubtract:
  940. result = (dst_result - src_result) / 255;
  941. break;
  942. // TODO: How do these two actually work?
  943. // OpenGL doesn't include the blend factors in the min/max computations,
  944. // but is this what the 3DS actually does?
  945. case Regs::BlendEquation::Min:
  946. result.r() = std::min(src.r(), dest.r());
  947. result.g() = std::min(src.g(), dest.g());
  948. result.b() = std::min(src.b(), dest.b());
  949. result.a() = std::min(src.a(), dest.a());
  950. break;
  951. case Regs::BlendEquation::Max:
  952. result.r() = std::max(src.r(), dest.r());
  953. result.g() = std::max(src.g(), dest.g());
  954. result.b() = std::max(src.b(), dest.b());
  955. result.a() = std::max(src.a(), dest.a());
  956. break;
  957. default:
  958. LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", equation);
  959. UNIMPLEMENTED();
  960. }
  961. return Math::Vec4<u8>(
  962. MathUtil::Clamp(result.r(), 0, 255), MathUtil::Clamp(result.g(), 0, 255),
  963. MathUtil::Clamp(result.b(), 0, 255), MathUtil::Clamp(result.a(), 0, 255));
  964. };
  965. auto srcfactor = Math::MakeVec(LookupFactor(0, params.factor_source_rgb),
  966. LookupFactor(1, params.factor_source_rgb),
  967. LookupFactor(2, params.factor_source_rgb),
  968. LookupFactor(3, params.factor_source_a));
  969. auto dstfactor = Math::MakeVec(LookupFactor(0, params.factor_dest_rgb),
  970. LookupFactor(1, params.factor_dest_rgb),
  971. LookupFactor(2, params.factor_dest_rgb),
  972. LookupFactor(3, params.factor_dest_a));
  973. blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor,
  974. params.blend_equation_rgb);
  975. blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest,
  976. dstfactor, params.blend_equation_a)
  977. .a();
  978. } else {
  979. static auto LogicOp = [](u8 src, u8 dest, Regs::LogicOp op) -> u8 {
  980. switch (op) {
  981. case Regs::LogicOp::Clear:
  982. return 0;
  983. case Regs::LogicOp::And:
  984. return src & dest;
  985. case Regs::LogicOp::AndReverse:
  986. return src & ~dest;
  987. case Regs::LogicOp::Copy:
  988. return src;
  989. case Regs::LogicOp::Set:
  990. return 255;
  991. case Regs::LogicOp::CopyInverted:
  992. return ~src;
  993. case Regs::LogicOp::NoOp:
  994. return dest;
  995. case Regs::LogicOp::Invert:
  996. return ~dest;
  997. case Regs::LogicOp::Nand:
  998. return ~(src & dest);
  999. case Regs::LogicOp::Or:
  1000. return src | dest;
  1001. case Regs::LogicOp::Nor:
  1002. return ~(src | dest);
  1003. case Regs::LogicOp::Xor:
  1004. return src ^ dest;
  1005. case Regs::LogicOp::Equiv:
  1006. return ~(src ^ dest);
  1007. case Regs::LogicOp::AndInverted:
  1008. return ~src & dest;
  1009. case Regs::LogicOp::OrReverse:
  1010. return src | ~dest;
  1011. case Regs::LogicOp::OrInverted:
  1012. return ~src | dest;
  1013. }
  1014. };
  1015. blend_output =
  1016. Math::MakeVec(LogicOp(combiner_output.r(), dest.r(), output_merger.logic_op),
  1017. LogicOp(combiner_output.g(), dest.g(), output_merger.logic_op),
  1018. LogicOp(combiner_output.b(), dest.b(), output_merger.logic_op),
  1019. LogicOp(combiner_output.a(), dest.a(), output_merger.logic_op));
  1020. }
  1021. const Math::Vec4<u8> result = {
  1022. output_merger.red_enable ? blend_output.r() : dest.r(),
  1023. output_merger.green_enable ? blend_output.g() : dest.g(),
  1024. output_merger.blue_enable ? blend_output.b() : dest.b(),
  1025. output_merger.alpha_enable ? blend_output.a() : dest.a(),
  1026. };
  1027. if (regs.framebuffer.allow_color_write != 0)
  1028. DrawPixel(x >> 4, y >> 4, result);
  1029. }
  1030. }
  1031. }
  1032. void ProcessTriangle(const Vertex& v0, const Vertex& v1, const Vertex& v2) {
  1033. ProcessTriangleInternal(v0, v1, v2);
  1034. }
  1035. } // namespace Rasterizer
  1036. } // namespace Pica