ScaleFactors.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. using Ryujinx.Common.Memory;
  2. using System.Runtime.CompilerServices;
  3. using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve;
  4. using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter;
  5. namespace Ryujinx.Graphics.Nvdec.Vp9.Types
  6. {
  7. internal struct ScaleFactors
  8. {
  9. private const int RefScaleShift = 14;
  10. private const int RefNoScale = (1 << RefScaleShift);
  11. private const int RefInvalidScale = -1;
  12. private unsafe delegate void ConvolveFn(
  13. byte* src,
  14. int srcStride,
  15. byte* dst,
  16. int dstStride,
  17. Array8<short>[] filter,
  18. int x0Q4,
  19. int xStepQ4,
  20. int y0Q4,
  21. int yStepQ4,
  22. int w,
  23. int h);
  24. private unsafe delegate void HighbdConvolveFn(
  25. ushort* src,
  26. int srcStride,
  27. ushort* dst,
  28. int dstStride,
  29. Array8<short>[] filter,
  30. int x0Q4,
  31. int xStepQ4,
  32. int y0Q4,
  33. int yStepQ4,
  34. int w,
  35. int h,
  36. int bd);
  37. private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][]
  38. {
  39. new ConvolveFn[][]
  40. {
  41. new ConvolveFn[]
  42. {
  43. ConvolveCopy,
  44. ConvolveAvg
  45. },
  46. new ConvolveFn[]
  47. {
  48. Convolve8Vert,
  49. Convolve8AvgVert
  50. }
  51. },
  52. new ConvolveFn[][]
  53. {
  54. new ConvolveFn[]
  55. {
  56. Convolve8Horiz,
  57. Convolve8AvgHoriz
  58. },
  59. new ConvolveFn[]
  60. {
  61. Convolve8,
  62. Convolve8Avg
  63. }
  64. }
  65. };
  66. private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][]
  67. {
  68. new ConvolveFn[][]
  69. {
  70. new ConvolveFn[]
  71. {
  72. ScaledVert,
  73. ScaledAvgVert
  74. },
  75. new ConvolveFn[]
  76. {
  77. ScaledVert,
  78. ScaledAvgVert
  79. }
  80. },
  81. new ConvolveFn[][]
  82. {
  83. new ConvolveFn[]
  84. {
  85. Scaled2D,
  86. ScaledAvg2D
  87. },
  88. new ConvolveFn[]
  89. {
  90. Scaled2D,
  91. ScaledAvg2D
  92. }
  93. }
  94. };
  95. private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][]
  96. {
  97. new ConvolveFn[][]
  98. {
  99. new ConvolveFn[]
  100. {
  101. ScaledHoriz,
  102. ScaledAvgHoriz
  103. },
  104. new ConvolveFn[]
  105. {
  106. Scaled2D,
  107. ScaledAvg2D
  108. }
  109. },
  110. new ConvolveFn[][]
  111. {
  112. new ConvolveFn[]
  113. {
  114. ScaledHoriz,
  115. ScaledAvgHoriz
  116. },
  117. new ConvolveFn[]
  118. {
  119. Scaled2D,
  120. ScaledAvg2D
  121. }
  122. }
  123. };
  124. private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
  125. {
  126. new ConvolveFn[][]
  127. {
  128. new ConvolveFn[]
  129. {
  130. Scaled2D,
  131. ScaledAvg2D
  132. },
  133. new ConvolveFn[]
  134. {
  135. Scaled2D,
  136. ScaledAvg2D
  137. }
  138. },
  139. new ConvolveFn[][]
  140. {
  141. new ConvolveFn[]
  142. {
  143. Scaled2D,
  144. ScaledAvg2D
  145. },
  146. new ConvolveFn[]
  147. {
  148. Scaled2D,
  149. ScaledAvg2D
  150. }
  151. }
  152. };
  153. private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][]
  154. {
  155. new HighbdConvolveFn[][]
  156. {
  157. new HighbdConvolveFn[]
  158. {
  159. HighbdConvolveCopy,
  160. HighbdConvolveAvg
  161. },
  162. new HighbdConvolveFn[]
  163. {
  164. HighbdConvolve8Vert,
  165. HighbdConvolve8AvgVert
  166. }
  167. },
  168. new HighbdConvolveFn[][]
  169. {
  170. new HighbdConvolveFn[]
  171. {
  172. HighbdConvolve8Horiz,
  173. HighbdConvolve8AvgHoriz
  174. },
  175. new HighbdConvolveFn[]
  176. {
  177. HighbdConvolve8,
  178. HighbdConvolve8Avg
  179. }
  180. }
  181. };
  182. private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][]
  183. {
  184. new HighbdConvolveFn[][]
  185. {
  186. new HighbdConvolveFn[]
  187. {
  188. HighbdConvolve8Vert,
  189. HighbdConvolve8AvgVert
  190. },
  191. new HighbdConvolveFn[]
  192. {
  193. HighbdConvolve8Vert,
  194. HighbdConvolve8AvgVert
  195. }
  196. },
  197. new HighbdConvolveFn[][]
  198. {
  199. new HighbdConvolveFn[]
  200. {
  201. HighbdConvolve8,
  202. HighbdConvolve8Avg
  203. },
  204. new HighbdConvolveFn[]
  205. {
  206. HighbdConvolve8,
  207. HighbdConvolve8Avg
  208. }
  209. }
  210. };
  211. private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][]
  212. {
  213. new HighbdConvolveFn[][]
  214. {
  215. new HighbdConvolveFn[]
  216. {
  217. HighbdConvolve8Horiz,
  218. HighbdConvolve8AvgHoriz
  219. },
  220. new HighbdConvolveFn[]
  221. {
  222. HighbdConvolve8,
  223. HighbdConvolve8Avg
  224. }
  225. },
  226. new HighbdConvolveFn[][]
  227. {
  228. new HighbdConvolveFn[]
  229. {
  230. HighbdConvolve8Horiz,
  231. HighbdConvolve8AvgHoriz
  232. },
  233. new HighbdConvolveFn[]
  234. {
  235. HighbdConvolve8,
  236. HighbdConvolve8Avg
  237. }
  238. }
  239. };
  240. private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
  241. {
  242. new HighbdConvolveFn[][]
  243. {
  244. new HighbdConvolveFn[]
  245. {
  246. HighbdConvolve8,
  247. HighbdConvolve8Avg
  248. },
  249. new HighbdConvolveFn[]
  250. {
  251. HighbdConvolve8,
  252. HighbdConvolve8Avg
  253. }
  254. },
  255. new HighbdConvolveFn[][]
  256. {
  257. new HighbdConvolveFn[]
  258. {
  259. HighbdConvolve8,
  260. HighbdConvolve8Avg
  261. },
  262. new HighbdConvolveFn[]
  263. {
  264. HighbdConvolve8,
  265. HighbdConvolve8Avg
  266. }
  267. }
  268. };
  269. public int XScaleFP; // Horizontal fixed point scale factor
  270. public int YScaleFP; // Vertical fixed point scale factor
  271. public int XStepQ4;
  272. public int YStepQ4;
  273. public int ScaleValueX(int val)
  274. {
  275. return IsScaled() ? ScaledX(val) : val;
  276. }
  277. public int ScaleValueY(int val)
  278. {
  279. return IsScaled() ? ScaledY(val) : val;
  280. }
  281. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  282. public unsafe void InterPredict(
  283. int horiz,
  284. int vert,
  285. int avg,
  286. byte* src,
  287. int srcStride,
  288. byte* dst,
  289. int dstStride,
  290. int subpelX,
  291. int subpelY,
  292. int w,
  293. int h,
  294. Array8<short>[] kernel,
  295. int xs,
  296. int ys)
  297. {
  298. if (XStepQ4 == 16)
  299. {
  300. if (YStepQ4 == 16)
  301. {
  302. // No scaling in either direction.
  303. PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
  304. }
  305. else
  306. {
  307. // No scaling in x direction. Must always scale in the y direction.
  308. PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
  309. }
  310. }
  311. else
  312. {
  313. if (YStepQ4 == 16)
  314. {
  315. // No scaling in the y direction. Must always scale in the x direction.
  316. PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
  317. }
  318. else
  319. {
  320. // Must always scale in both directions.
  321. Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
  322. }
  323. }
  324. }
  325. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  326. public unsafe void HighbdInterPredict(
  327. int horiz,
  328. int vert,
  329. int avg,
  330. ushort* src,
  331. int srcStride,
  332. ushort* dst,
  333. int dstStride,
  334. int subpelX,
  335. int subpelY,
  336. int w,
  337. int h,
  338. Array8<short>[] kernel,
  339. int xs,
  340. int ys,
  341. int bd)
  342. {
  343. if (XStepQ4 == 16)
  344. {
  345. if (YStepQ4 == 16)
  346. {
  347. // No scaling in either direction.
  348. HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
  349. }
  350. else
  351. {
  352. // No scaling in x direction. Must always scale in the y direction.
  353. HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
  354. }
  355. }
  356. else
  357. {
  358. if (YStepQ4 == 16)
  359. {
  360. // No scaling in the y direction. Must always scale in the x direction.
  361. HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
  362. }
  363. else
  364. {
  365. // Must always scale in both directions.
  366. HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
  367. }
  368. }
  369. }
  370. private int ScaledX(int val)
  371. {
  372. return (int)((long)val * XScaleFP >> RefScaleShift);
  373. }
  374. private int ScaledY(int val)
  375. {
  376. return (int)((long)val * YScaleFP >> RefScaleShift);
  377. }
  378. private static int GetFixedPointScaleFactor(int otherSize, int thisSize)
  379. {
  380. // Calculate scaling factor once for each reference frame
  381. // and use fixed point scaling factors in decoding and encoding routines.
  382. // Hardware implementations can calculate scale factor in device driver
  383. // and use multiplication and shifting on hardware instead of division.
  384. return (otherSize << RefScaleShift) / thisSize;
  385. }
  386. public Mv32 ScaleMv(ref Mv mv, int x, int y)
  387. {
  388. int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
  389. int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
  390. Mv32 res = new Mv32()
  391. {
  392. Row = ScaledY(mv.Row) + yOffQ4,
  393. Col = ScaledX(mv.Col) + xOffQ4
  394. };
  395. return res;
  396. }
  397. public bool IsValidScale()
  398. {
  399. return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
  400. }
  401. public bool IsScaled()
  402. {
  403. return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
  404. }
  405. public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
  406. {
  407. return 2 * thisWidth >= refWidth &&
  408. 2 * thisHeight >= refHeight &&
  409. thisWidth <= 16 * refWidth &&
  410. thisHeight <= 16 * refHeight;
  411. }
  412. public void SetupScaleFactorsForFrame(int otherW, int otherH, int thisW, int thisH)
  413. {
  414. if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
  415. {
  416. XScaleFP = RefInvalidScale;
  417. YScaleFP = RefInvalidScale;
  418. return;
  419. }
  420. XScaleFP = GetFixedPointScaleFactor(otherW, thisW);
  421. YScaleFP = GetFixedPointScaleFactor(otherH, thisH);
  422. XStepQ4 = ScaledX(16);
  423. YStepQ4 = ScaledY(16);
  424. }
  425. }
  426. }