upscale.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /*
  2. * upscale.c image upscaling
  3. *
  4. * This file contains upscalers for picodrive.
  5. *
  6. * scaler types:
  7. * nn: nearest neighbour
  8. * snn: "smoothed" nearest neighbour (see below)
  9. * bln: n-level-bilinear with n quantized weights
  10. * quantization: 0: a<1/(2*n), 1/n: 1/(2*n)<=a<3/(2*n), etc
  11. * currently n=2, n=4 are implemented (there's n=8 mixing, but no filters)
  12. * [NB this has been brought to my attn, which is probably the same as bl2:
  13. * https://www.drdobbs.com/image-scaling-with-bresenham/184405045?pgno=1]
  14. *
  15. * "smoothed" nearest neighbour: uses the average of the source pixels if no
  16. * source pixel covers more than 65% of the result pixel. It definitely
  17. * looks better than nearest neighbour and is still quite fast. It creates
  18. * a sharper look than a bilinear filter, at the price of some visible jags
  19. * on diagonal edges.
  20. *
  21. * example scaling modes:
  22. * 256x_Y_ -> 320x_Y_, H32/mode 4, PAR 5:4, for PAL DAR 4:3 (NTSC 7% aspect err)
  23. * 256x224 -> 320x240, H32/mode 4, PAR 5:4, for NTSC DAR 4:3 (PAL 7% aspect err)
  24. * 320x224 -> 320x240, PAR 1:1, for NTSC, DAR 4:3 (PAL 7% etc etc...)
  25. * 160x144 -> 320x240: GG, PAR 6:5, scaling to 320x240 for DAR 4:3
  26. *
  27. * (C) 2021 kub <derkub@gmail.com>
  28. *
  29. * This work is licensed under the terms of any of these licenses
  30. * (at your option):
  31. * - GNU GPL, version 2 or later.
  32. * - MAME license.
  33. */
  34. #include "upscale.h"
  35. /* X x Y -> X*5/4 x Y */
  36. void upscale_clut_nn_x_4_5(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
  37. {
  38. int y;
  39. for (y = 0; y < height; y++) {
  40. h_upscale_nn_4_5(di, ds, si, ss, width, f_nop);
  41. }
  42. }
  43. void upscale_rgb_nn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  44. {
  45. int y;
  46. for (y = 0; y < height; y++) {
  47. h_upscale_nn_4_5(di, ds, si, ss, width, f_pal);
  48. }
  49. }
  50. void upscale_rgb_snn_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  51. {
  52. int y;
  53. for (y = 0; y < height; y++) {
  54. h_upscale_snn_4_5(di, ds, si, ss, width, f_pal);
  55. }
  56. }
  57. void upscale_rgb_bl2_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  58. {
  59. int y;
  60. for (y = 0; y < height; y++) {
  61. h_upscale_bl2_4_5(di, ds, si, ss, width, f_pal);
  62. }
  63. }
  64. void upscale_rgb_bl4_x_4_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  65. {
  66. int y;
  67. for (y = 0; y < height; y++) {
  68. h_upscale_bl4_4_5(di, ds, si, ss, width, f_pal);
  69. }
  70. }
  71. /* X x Y -> X*5/4 x Y*17/16 */
  72. void upscale_clut_nn_x_4_5_y_16_17(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
  73. {
  74. int swidth = width * 5/4;
  75. int y, j;
  76. for (y = 0; y < height; y += 16) {
  77. for (j = 0; j < 8; j++) {
  78. h_upscale_nn_4_5(di, ds, si, ss, width, f_nop);
  79. }
  80. di += ds;
  81. for (j = 0; j < 8; j++) {
  82. h_upscale_nn_4_5(di, ds, si, ss, width, f_nop);
  83. }
  84. di -= 9*ds;
  85. v_copy(&di[0], &di[-ds], swidth, f_nop);
  86. di += 9*ds;
  87. }
  88. }
  89. void upscale_rgb_nn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  90. {
  91. int swidth = width * 5/4;
  92. int y, j;
  93. for (y = 0; y < height; y += 16) {
  94. for (j = 0; j < 8; j++) {
  95. h_upscale_nn_4_5(di, ds, si, ss, width, f_pal);
  96. }
  97. di += ds;
  98. for (j = 0; j < 8; j++) {
  99. h_upscale_nn_4_5(di, ds, si, ss, width, f_pal);
  100. }
  101. di -= 9*ds;
  102. v_copy(&di[0], &di[-ds], swidth, f_nop);
  103. di += 9*ds;
  104. }
  105. }
  106. void upscale_rgb_snn_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  107. {
  108. int swidth = width * 5/4;
  109. int y, j;
  110. for (y = 0; y < height; y += 16) {
  111. for (j = 0; j < 8; j++) {
  112. h_upscale_snn_4_5(di, ds, si, ss, width, f_pal);
  113. }
  114. di += ds;
  115. for (j = 0; j < 8; j++) {
  116. h_upscale_snn_4_5(di, ds, si, ss, width, f_pal);
  117. }
  118. /* mix lines 6-8 */
  119. di -= 9*ds;
  120. v_mix(&di[0], &di[-ds], &di[ds], swidth, p_05, f_nop);
  121. v_mix(&di[-ds], &di[-2*ds], &di[-ds], swidth, p_05, f_nop);
  122. v_mix(&di[ ds], &di[ ds], &di[ 2*ds], swidth, p_05, f_nop);
  123. di += 9*ds;
  124. }
  125. }
  126. void upscale_rgb_bl2_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  127. {
  128. int swidth = width * 5/4;
  129. int y, j;
  130. for (y = 0; y < height; y += 16) {
  131. for (j = 0; j < 4; j++) {
  132. h_upscale_bl2_4_5(di, ds, si, ss, width, f_pal);
  133. }
  134. di += ds;
  135. for (j = 0; j < 12; j++) {
  136. h_upscale_bl2_4_5(di, ds, si, ss, width, f_pal);
  137. }
  138. /* mix lines 3-10 */
  139. di -= 13*ds;
  140. v_mix(&di[0], &di[-ds], &di[ds], swidth, p_05, f_nop);
  141. for (j = 0; j < 7; j++) {
  142. di += ds;
  143. v_mix(&di[0], &di[0], &di[ds], swidth, p_05, f_nop);
  144. }
  145. di += 6*ds;
  146. }
  147. }
  148. void upscale_rgb_bl4_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  149. {
  150. int swidth = width * 5/4;
  151. int y, j;
  152. for (y = 0; y < height; y += 16) {
  153. for (j = 0; j < 2; j++) {
  154. h_upscale_bl4_4_5(di, ds, si, ss, width, f_pal);
  155. }
  156. di += ds;
  157. for (j = 0; j < 14; j++) {
  158. h_upscale_bl4_4_5(di, ds, si, ss, width, f_pal);
  159. }
  160. di -= 15*ds;
  161. /* mixing line 2: line 1 = -ds, line 2 = +ds */
  162. v_mix(&di[0], &di[-ds], &di[ds], swidth, p_025, f_nop);
  163. di += ds;
  164. /* mixing lines 3-5: line n-1 = 0, line n = +ds */
  165. for (j = 0; j < 3; j++) {
  166. v_mix(&di[0], &di[0], &di[ds], swidth, p_025, f_nop);
  167. di += ds;
  168. }
  169. /* mixing lines 6-9 */
  170. for (j = 0; j < 4; j++) {
  171. v_mix(&di[0], &di[0], &di[ds], swidth, p_05, f_nop);
  172. di += ds;
  173. }
  174. /* mixing lines 10-13 */
  175. for (j = 0; j < 4; j++) {
  176. v_mix(&di[0], &di[0], &di[ds], swidth, p_075, f_nop);
  177. di += ds;
  178. }
  179. /* lines 14-16, already in place */
  180. di += 3*ds;
  181. }
  182. }
  183. /* "classic" upscaler as found in several emulators. It's really more like a
  184. * x*4/3, y*16/15 upscaler, with an additional 5th row/17th line just inserted
  185. * from the source image. That gives nice n/4,n/16 alpha values plus better
  186. * symmetry in each block and avoids "borrowing" a row/line between blocks.
  187. */
  188. void upscale_rgb_bln_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  189. {
  190. int swidth = width * 5/4;
  191. int y, j;
  192. for (y = 0; y < height; y += 16) {
  193. for (j = 0; j < 4; j++) {
  194. h_upscale_bln_4_5(di, ds, si, ss, width, f_pal);
  195. }
  196. di += ds;
  197. for (j = 0; j < 12; j++) {
  198. h_upscale_bln_4_5(di, ds, si, ss, width, f_pal);
  199. }
  200. di -= 13*ds;
  201. /* mixing line 4: line 3 = -ds, line 4 = +ds */
  202. v_mix(&di[0], &di[-ds], &di[ds], swidth, p_025, f_nop);
  203. di += ds;
  204. /* mixing lines 5-6: line n-1 = 0, line n = +ds */
  205. for (j = 0; j < 2; j++) {
  206. v_mix(&di[0], &di[0], &di[ds], swidth, p_025, f_nop);
  207. di += ds;
  208. }
  209. /* mixing line 7-9 */
  210. for (j = 0; j < 3; j++) {
  211. v_mix(&di[0], &di[0], &di[ds], swidth, p_05, f_nop);
  212. di += ds;
  213. }
  214. /* mixing lines 10-12 */
  215. for (j = 0; j < 3; j++) {
  216. v_mix(&di[0], &di[0], &di[ds], swidth, p_075, f_nop);
  217. di += ds;
  218. }
  219. /* lines 13-16, already in place */
  220. di += 4*ds;
  221. }
  222. }
  223. /* experimental 8 level bilinear for quality assessment */
  224. void upscale_rgb_bl8_x_4_5_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  225. {
  226. int swidth = width * 5/4;
  227. int y, j;
  228. for (y = 0; y < 224; y += 16) {
  229. for (j = 0; j < 2; j++) {
  230. h_upscale_bl8_4_5(di, ds, si, ss, width, f_pal);
  231. }
  232. di += ds;
  233. for (j = 0; j < 14; j++) {
  234. h_upscale_bl8_4_5(di, ds, si, ss, width, f_pal);
  235. }
  236. di -= 15*ds;
  237. /* mixing line 2: line 2 = -ds, line 3 = +ds */
  238. v_mix(&di[0], &di[-ds], &di[ds], swidth, p_0125, f_nop);
  239. di += ds;
  240. /* mixing line 3: line 3 = 0, line 4 = +ds */
  241. v_mix(&di[0], &di[0], &di[ds], swidth, p_0125, f_nop);
  242. di += ds;
  243. /* mixing lines 4-5: line n-1 = 0, line n = +ds */
  244. for (j = 0; j < 2; j++) {
  245. v_mix(&di[0], &di[0], &di[ds], swidth, p_025, f_nop);
  246. di += ds;
  247. }
  248. /* mixing lines 6-7 */
  249. for (j = 0; j < 2; j++) {
  250. v_mix(&di[0], &di[0], &di[ds], 320, p_0375, f_nop);
  251. di += ds;
  252. }
  253. /* mixing lines 8-9 */
  254. for (j = 0; j < 2; j++) {
  255. v_mix(&di[0], &di[0], &di[ds], 320, p_05, f_nop);
  256. di += ds;
  257. }
  258. /* mixing lines 10-11 */
  259. for (j = 0; j < 2; j++) {
  260. v_mix(&di[0], &di[0], &di[ds], 320, p_0625, f_nop);
  261. di += ds;
  262. }
  263. /* mixing lines 12-13 */
  264. for (j = 0; j < 2; j++) {
  265. v_mix(&di[0], &di[0], &di[ds], 320, p_075, f_nop);
  266. di += ds;
  267. }
  268. /* mixing lines 14-15 */
  269. for (j = 0; j < 2; j++) {
  270. v_mix(&di[0], &di[0], &di[ds], 320, p_0875, f_nop);
  271. di += ds;
  272. }
  273. /* line 16, already in place */
  274. di += ds;
  275. }
  276. }
  277. /* X x Y -> X x Y*17/16 */
  278. void upscale_clut_nn_y_16_17(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
  279. {
  280. int y, j;
  281. for (y = 0; y < height; y += 16) {
  282. for (j = 0; j < 8; j++) {
  283. h_copy(di, ds, si, ss, width, f_nop);
  284. }
  285. di += ds;
  286. for (j = 0; j < 8; j++) {
  287. h_copy(di, ds, si, ss, width, f_nop);
  288. }
  289. di -= 9*ds;
  290. v_copy(&di[0], &di[-ds], width, f_nop);
  291. di += 9*ds;
  292. }
  293. }
  294. void upscale_rgb_nn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  295. {
  296. int y, j;
  297. for (y = 0; y < height; y += 16) {
  298. for (j = 0; j < 8; j++) {
  299. h_copy(di, ds, si, ss, width, f_pal);
  300. }
  301. di += ds;
  302. for (j = 0; j < 8; j++) {
  303. h_copy(di, ds, si, ss, width, f_pal);
  304. }
  305. di -= 9*ds;
  306. v_copy(&di[0], &di[-ds], width, f_nop);
  307. di += 9*ds;
  308. }
  309. }
  310. void upscale_rgb_snn_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  311. {
  312. int y, j;
  313. for (y = 0; y < height; y += 16) {
  314. for (j = 0; j < 8; j++) {
  315. h_copy(di, ds, si, ss, width, f_pal);
  316. }
  317. di += ds;
  318. for (j = 0; j < 8; j++) {
  319. h_copy(di, ds, si, ss, width, f_pal);
  320. }
  321. /* mix lines 6-8 */
  322. di -= 9*ds;
  323. v_mix(&di[0], &di[-ds], &di[ds], width, p_05, f_nop);
  324. v_mix(&di[-ds], &di[-2*ds], &di[-ds], width, p_05, f_nop);
  325. v_mix(&di[ ds], &di[ ds], &di[ 2*ds], width, p_05, f_nop);
  326. di += 9*ds;
  327. }
  328. }
  329. void upscale_rgb_bl2_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  330. {
  331. int y, j;
  332. for (y = 0; y < height; y += 16) {
  333. for (j = 0; j < 4; j++) {
  334. h_copy(di, ds, si, ss, width, f_pal);
  335. }
  336. di += ds;
  337. for (j = 0; j < 12; j++) {
  338. h_copy(di, ds, si, ss, width, f_pal);
  339. }
  340. /* mix lines 4-11 */
  341. di -= 13*ds;
  342. v_mix(&di[0], &di[-ds], &di[ds], width, p_05, f_nop);
  343. for (j = 0; j < 7; j++) {
  344. di += ds;
  345. v_mix(&di[0], &di[0], &di[ds], width, p_05, f_nop);
  346. }
  347. di += 6*ds;
  348. }
  349. }
  350. void upscale_rgb_bl4_y_16_17(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  351. {
  352. int y, j;
  353. for (y = 0; y < height; y += 16) {
  354. for (j = 0; j < 2; j++) {
  355. h_copy(di, ds, si, ss, width, f_pal);
  356. }
  357. di += ds;
  358. for (j = 0; j < 14; j++) {
  359. h_copy(di, ds, si, ss, width, f_pal);
  360. }
  361. di -= 15*ds;
  362. /* mixing line 2: line 1 = -ds, line 2 = +ds */
  363. v_mix(&di[0], &di[-ds], &di[ds], width, p_025, f_nop);
  364. di += ds;
  365. /* mixing lines 3-5: line n-1 = 0, line n = +ds */
  366. for (j = 0; j < 3; j++) {
  367. v_mix(&di[0], &di[0], &di[ds], width, p_025, f_nop);
  368. di += ds;
  369. }
  370. /* mixing lines 6-9 */
  371. for (j = 0; j < 4; j++) {
  372. v_mix(&di[0], &di[0], &di[ds], width, p_05, f_nop);
  373. di += ds;
  374. }
  375. /* mixing lines 10-13 */
  376. for (j = 0; j < 4; j++) {
  377. v_mix(&di[0], &di[0], &di[ds], width, p_075, f_nop);
  378. di += ds;
  379. }
  380. /* lines 14-16, already in place */
  381. di += 3*ds;
  382. }
  383. }
  384. /* X x Y -> X*2/1 x Y, e.g. for X 160->320 (GG) */
  385. void upscale_clut_nn_x_1_2(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
  386. {
  387. int y;
  388. for (y = 0; y < height; y++) {
  389. h_upscale_nn_1_2(di, ds, si, ss, width, f_nop);
  390. }
  391. }
  392. void upscale_rgb_nn_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  393. {
  394. int y;
  395. for (y = 0; y < height; y++) {
  396. h_upscale_nn_1_2(di, ds, si, ss, width, f_pal);
  397. }
  398. }
  399. void upscale_rgb_bl2_x_1_2(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  400. {
  401. int y;
  402. for (y = 0; y < height; y++) {
  403. h_upscale_bl2_1_2(di, ds, si, ss, width, f_pal);
  404. }
  405. }
  406. /* X x Y -> X*2/1 x Y*5/3 (GG) */
  407. void upscale_clut_nn_x_1_2_y_3_5(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
  408. {
  409. int swidth = width * 2;
  410. int y, j;
  411. for (y = 0; y < height; y += 3) {
  412. /* lines 0,2,4 */
  413. for (j = 0; j < 3; j++) {
  414. h_upscale_nn_1_2(di, ds, si, ss, width, f_nop);
  415. di += ds;
  416. }
  417. /* lines 1,3 */
  418. di -= 5*ds;
  419. for (j = 0; j < 2; j++) {
  420. v_copy(&di[0], &di[-ds], swidth, f_nop);
  421. di += 2*ds;
  422. }
  423. }
  424. }
  425. void upscale_rgb_nn_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  426. {
  427. int swidth = width * 2;
  428. int y, j;
  429. for (y = 0; y < height; y += 3) {
  430. for (j = 0; j < 3; j++) {
  431. h_upscale_nn_1_2(di, ds, si, ss, width, f_pal);
  432. di += ds;
  433. }
  434. di -= 5*ds;
  435. for (j = 0; j < 2; j++) {
  436. v_copy(&di[0], &di[-ds], swidth, f_nop);
  437. di += 2*ds;
  438. }
  439. }
  440. }
  441. void upscale_rgb_bl2_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  442. {
  443. int swidth = width * 2;
  444. int y, j;
  445. for (y = 0; y < height; y += 3) {
  446. for (j = 0; j < 3; j++) {
  447. h_upscale_bl2_1_2(di, ds, si, ss, width, f_pal);
  448. di += ds;
  449. }
  450. di -= 5*ds;
  451. for (j = 0; j < 2; j++) {
  452. v_mix(&di[0], &di[-ds], &di[ds], swidth, p_05, f_nop);
  453. di += 2*ds;
  454. }
  455. }
  456. }
  457. void upscale_rgb_bl4_x_1_2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  458. {
  459. int swidth = width * 2;
  460. int y, j, d;
  461. /* for 1st block backwards reference virtually duplicate source line 0 */
  462. for (y = 0, d = 2*ds; y < height; y += 3, d = -ds) {
  463. di += 2*ds;
  464. for (j = 0; j < 3; j++) {
  465. h_upscale_bl2_1_2(di, ds, si, ss, width, f_pal);
  466. }
  467. di -= 5*ds;
  468. v_mix(&di[0], &di[d ], &di[2*ds], swidth, p_05, f_nop); /*-1+0 */
  469. di += ds;
  470. v_mix(&di[0], &di[ds], &di[2*ds], swidth, p_075, f_nop);/* 0+1 */
  471. di += ds;
  472. v_mix(&di[0], &di[ 0], &di[ ds], swidth, p_025, f_nop);/* 0+1 */
  473. di += ds;
  474. v_mix(&di[0], &di[ 0], &di[ ds], swidth, p_05, f_nop); /* 1+2 */
  475. di += 2*ds;
  476. }
  477. }
  478. /* X x Y -> X x Y*5/3, e.g. for Y 144->240 (GG) */
  479. void upscale_clut_nn_y_3_5(u8 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height)
  480. {
  481. int y, j;
  482. for (y = 0; y < height; y += 3) {
  483. /* lines 0,2,4 */
  484. for (j = 0; j < 3; j++) {
  485. h_copy(di, ds, si, ss, width, f_nop);
  486. di += ds;
  487. }
  488. /* lines 1,3 */
  489. di -= 5*ds;
  490. for (j = 0; j < 2; j++) {
  491. v_copy(&di[0], &di[-ds], width, f_nop);
  492. di += 2*ds;
  493. }
  494. }
  495. }
  496. void upscale_rgb_nn_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  497. {
  498. int y, j;
  499. for (y = 0; y < height; y += 3) {
  500. for (j = 0; j < 3; j++) {
  501. h_copy(di, ds, si, ss, width, f_pal);
  502. di += ds;
  503. }
  504. di -= 5*ds;
  505. for (j = 0; j < 2; j++) {
  506. v_copy(&di[0], &di[-ds], width, f_nop);
  507. di += 2*ds;
  508. }
  509. }
  510. }
  511. void upscale_rgb_bl2_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  512. {
  513. int y, j;
  514. for (y = 0; y < height; y += 3) {
  515. for (j = 0; j < 3; j++) {
  516. h_copy(di, ds, si, ss, width, f_pal);
  517. di += ds;
  518. }
  519. di -= 5*ds;
  520. for (j = 0; j < 2; j++) {
  521. v_mix(&di[0], &di[-ds], &di[ds], width, p_05, f_nop);
  522. di += 2*ds;
  523. }
  524. }
  525. }
  526. void upscale_rgb_bl4_y_3_5(u16 *__restrict di, int ds, u8 *__restrict si, int ss, int width, int height, u16 *pal)
  527. {
  528. int y, j, d;
  529. /* for 1st block backwards reference virtually duplicate source line 0 */
  530. for (y = 0, d = 2*ds; y < height; y += 3, d = -ds) {
  531. di += 2*ds;
  532. for (j = 0; j < 3; j++) {
  533. h_copy(di, ds, si, ss, width, f_pal);
  534. }
  535. di -= 5*ds;
  536. v_mix(&di[0], &di[d ], &di[2*ds], width, p_05, f_nop); /*-1+0 */
  537. di += ds;
  538. v_mix(&di[0], &di[ds], &di[2*ds], width, p_075, f_nop);/* 0+1 */
  539. di += ds;
  540. v_mix(&di[0], &di[ 0], &di[ ds], width, p_025, f_nop);/* 0+1 */
  541. di += ds;
  542. v_mix(&di[0], &di[ 0], &di[ ds], width, p_05, f_nop); /* 1+2 */
  543. di += 2*ds;
  544. }
  545. }