rasterizer.cpp 52 KB

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