sw_rotate.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175
  1. /*
  2. * Copyright (c) 2020 Actions Technology Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <display/sw_draw.h>
  7. #include <display/sw_rotate.h>
  8. #include <assert.h>
  9. #ifdef CONFIG_GUI_API_BROM
  10. # include <brom_interface.h>
  11. #endif
  12. #ifndef MAX
  13. #define MAX(a, b) (((a) > (b)) ? (a) : (b))
  14. #endif
  15. #ifndef MIN
  16. #define MIN(a, b) (((a) < (b)) ? (a) : (b))
  17. #endif
  18. /*
  19. * compute x range in pixels inside the src image
  20. *
  21. * The routine will update the range value [*x_min, *x_max].
  22. *
  23. * @param x_min address of minimum range value in pixels
  24. * @param x_max address of maximum range value in pixels
  25. * @param img_w source image width in pixels
  26. * @param img_h source image height in pixels
  27. * @param start_x X coord of start point in fixedpoint-16, corresponding to the original *x_min value
  28. * @param start_y Y coord of start point in fixedpoint-16, corresponding to the original *x_min value
  29. * @param dx_x X coord of point delta in x direction in fixedpoint-16
  30. * @param dx_y Y coord of point delta in x direction in fixedpoint-16
  31. *
  32. * @return N/A
  33. */
  34. static inline void sw_transform_compoute_x_range(
  35. int32_t *x_min, int32_t *x_max, int16_t img_w, int16_t img_h,
  36. int32_t start_x, int32_t start_y, int32_t dx_x, int32_t dx_y)
  37. {
  38. const int32_t img_w_m1 = FIXEDPOINT16(img_w - 1);
  39. const int32_t img_h_m1 = FIXEDPOINT16(img_h - 1);
  40. int x_1, x_2;
  41. /* FIXME: the compiler seems to divide towards to zero. */
  42. if (dx_x != 0) {
  43. /*
  44. * floor(Δx * dx_x + start_x) >= FIXEDPOINT16(0)
  45. * ceil(Δx * dx_x + start_x) <= img_w_m1
  46. */
  47. if (dx_x > 0) {
  48. x_1 = (FIXEDPOINT16(0) - start_x + dx_x - 1) / dx_x;
  49. x_2 = (img_w_m1 - start_x) / dx_x;
  50. } else {
  51. x_2 = (FIXEDPOINT16(0) - start_x) / dx_x;
  52. x_1 = (img_w_m1 - start_x + dx_x + 1) / dx_x;
  53. }
  54. *x_min = MAX(*x_min, x_1);
  55. *x_max = MIN(*x_max, x_2);
  56. } else if (start_x < FIXEDPOINT16(0) || start_x > img_w_m1) {
  57. *x_max = *x_min - 1;
  58. return;
  59. }
  60. if (dx_y != 0) {
  61. /*
  62. * floor(Δy * dx_y + start_y) >= FIXEDPOINT16(0)
  63. * ceil(Δy * dx_y + start_y) <= img_h_m1
  64. */
  65. if (dx_y > 0) {
  66. x_1 = (FIXEDPOINT16(0) - start_y + dx_y - 1) / dx_y;
  67. x_2 = (img_h_m1 - start_y) / dx_y;
  68. } else {
  69. x_2 = (FIXEDPOINT16(0) - start_y) / dx_y;
  70. x_1 = (img_h_m1 - start_y + dx_y + 1) / dx_y;
  71. }
  72. *x_min = MAX(*x_min, x_1);
  73. *x_max = MIN(*x_max, x_2);
  74. } else if (start_y < FIXEDPOINT16(0) || start_y > img_h_m1) {
  75. *x_max = *x_min - 1;
  76. return;
  77. }
  78. }
  79. void sw_transform_config(int16_t img_x, int16_t img_y,
  80. int16_t pivot_x, int16_t pivot_y, uint16_t angle,
  81. uint16_t scale_x, uint16_t scale_y, uint16_t scale_bits,
  82. sw_matrix_t *matrix)
  83. {
  84. const uint16_t scale_factor = (1 << scale_bits);
  85. uint16_t revert_scale_x;
  86. uint16_t revert_scale_y;
  87. uint16_t revert_angle;
  88. assert(angle <= 3600 && scale_x > 0 && scale_y > 0);
  89. revert_scale_x = (scale_x > 0) ? (scale_factor * scale_factor / scale_x) : 1;
  90. revert_scale_y = (scale_x == scale_y) ? revert_scale_x :
  91. ((scale_y > 0) ? (scale_factor * scale_factor / scale_y) : 1);
  92. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  93. if (revert_scale_x == revert_scale_y) {
  94. p_brom_libgui_api->p_sw_transform_config(img_x, img_y,
  95. pivot_x, pivot_y, angle, revert_scale_x, revert_scale_y, scale_bits, matrix);
  96. return;
  97. }
  98. #endif
  99. revert_angle = 3600 - angle;
  100. /* coordinates in the destination coordinate system */
  101. matrix->tx = PX_FIXEDPOINT16(0);
  102. matrix->ty = PX_FIXEDPOINT16(0);
  103. matrix->sx = FIXEDPOINT16(1);
  104. matrix->shy = FIXEDPOINT16(0);
  105. matrix->shx = FIXEDPOINT16(0);
  106. matrix->sy = FIXEDPOINT16(1);
  107. /* transform back to the source coordinate system (rotate -> scaling) */
  108. sw_transform_point32_rot_first(&matrix->tx, &matrix->ty, matrix->tx, matrix->ty,
  109. PX_FIXEDPOINT16(img_x + pivot_x), PX_FIXEDPOINT16(img_y + pivot_y),
  110. revert_angle, revert_scale_x, revert_scale_y, scale_bits);
  111. sw_transform_point32_rot_first(&matrix->sx, &matrix->shy, matrix->sx, matrix->shy,
  112. FIXEDPOINT16(0), FIXEDPOINT16(0), revert_angle,
  113. revert_scale_x, revert_scale_y, scale_bits);
  114. sw_transform_point32_rot_first(&matrix->shx, &matrix->sy, matrix->shx, matrix->sy,
  115. FIXEDPOINT16(0), FIXEDPOINT16(0), revert_angle,
  116. revert_scale_x, revert_scale_y, scale_bits);
  117. /* map to the source pixel coordinate system */
  118. matrix->tx -= PX_FIXEDPOINT16(img_x);
  119. matrix->ty -= PX_FIXEDPOINT16(img_y);
  120. }
  121. void sw_transform_config_with_mode(uint16_t img_w, uint16_t img_h,
  122. uint8_t mode, sw_matrix_t *matrix)
  123. {
  124. switch (mode) {
  125. case SW_ROT_90:
  126. *matrix = (sw_matrix_t) {
  127. .sx = 0, .shx = FIXEDPOINT16(1), .tx = 0,
  128. .shy = FIXEDPOINT16(-1), .sy = 0, .ty = FIXEDPOINT16(img_h - 1),
  129. };
  130. break;
  131. case SW_ROT_180:
  132. *matrix = (sw_matrix_t) {
  133. .sx = FIXEDPOINT16(-1), .shx = 0, .tx = FIXEDPOINT16(img_w - 1),
  134. .shy = 0, .sy = FIXEDPOINT16(-1), .ty = FIXEDPOINT16(img_h - 1),
  135. };
  136. break;
  137. case SW_ROT_270:
  138. *matrix = (sw_matrix_t) {
  139. .sx = 0, .shx = FIXEDPOINT16(-1), .tx = FIXEDPOINT16(img_w - 1),
  140. .shy = FIXEDPOINT16(1), .sy = 0, .ty = 0,
  141. };
  142. break;
  143. case SW_FLIP_H:
  144. *matrix = (sw_matrix_t) {
  145. .sx = FIXEDPOINT16(-1), .shx = 0, .tx = FIXEDPOINT16(img_w - 1),
  146. .shy = 0, .sy = FIXEDPOINT16(1), .ty = 0,
  147. };
  148. break;
  149. case SW_FLIP_V:
  150. *matrix = (sw_matrix_t) {
  151. .sx = FIXEDPOINT16(1), .shx = 0, .tx = 0,
  152. .shy = 0, .sy = FIXEDPOINT16(-1), .ty = FIXEDPOINT16(img_h - 1),
  153. };
  154. break;
  155. default:
  156. *matrix = (sw_matrix_t) {
  157. .sx = FIXEDPOINT16(1), .shx = 0, .tx = 0,
  158. .shy = 0, .sy = FIXEDPOINT16(1), .ty = 0,
  159. };
  160. break;
  161. }
  162. }
  163. void sw_transform_rgb565_over_rgb565(void *dst, const void *src,
  164. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  165. int16_t x, int16_t y, uint16_t w, uint16_t h,
  166. const sw_matrix_t *matrix)
  167. {
  168. #ifdef CONFIG_GUI_API_BROM_LARK
  169. if (src_pitch == src_w * 2) {
  170. p_brom_libgui_api->p_sw_rotate_rgb565_over_rgb565(
  171. dst, src, dst_pitch / 2, src_w, src_h, x, y, w, h, matrix);
  172. return;
  173. }
  174. #endif
  175. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  176. p_brom_libgui_api->p_sw_transform_rgb565_over_rgb565(
  177. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  178. #else
  179. uint8_t * dst8 = dst;
  180. uint16_t src_bytes_per_pixel = 2;
  181. int32_t src_coord_x = matrix->tx +
  182. y * matrix->shx + x * matrix->sx;
  183. int32_t src_coord_y = matrix->ty +
  184. y * matrix->sy + x * matrix->shy;
  185. for (int j = h; j > 0; j--) {
  186. int32_t p_x = src_coord_x;
  187. int32_t p_y = src_coord_y;
  188. uint16_t *tmp_dst = (uint16_t *)dst8;
  189. int x1 = 0, x2 = w - 1;
  190. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  191. p_x, p_y, matrix->sx, matrix->shy);
  192. if (x1 > x2) {
  193. goto next_line;
  194. } else if (x1 > 0) {
  195. p_x += matrix->sx * x1;
  196. p_y += matrix->shy * x1;
  197. tmp_dst += x1;
  198. }
  199. for (int i = x2 - x1; i >= 0; i--) {
  200. int x = FLOOR_FIXEDPOINT16(p_x);
  201. int y = FLOOR_FIXEDPOINT16(p_y);
  202. int x_frac = p_x - FIXEDPOINT16(x);
  203. int y_frac = p_y - FIXEDPOINT16(y);
  204. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  205. uint8_t *src2 = src1 + src_bytes_per_pixel;
  206. uint8_t *src3 = src1 + src_pitch;
  207. uint8_t *src4 = src2 + src_pitch;
  208. *tmp_dst = bilinear_rgb565_fast_m6(*(uint16_t*)src1,
  209. *(uint16_t*)src2, *(uint16_t*)src3, *(uint16_t*)src4,
  210. x_frac >> 10, y_frac >> 10, 6);
  211. tmp_dst += 1;
  212. p_x += matrix->sx;
  213. p_y += matrix->shy;
  214. }
  215. next_line:
  216. src_coord_x += matrix->shx;
  217. src_coord_y += matrix->sy;
  218. dst8 += dst_pitch;
  219. }
  220. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  221. }
  222. void sw_transform_rgb565_over_rgb888(void *dst, const void *src,
  223. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  224. int16_t x, int16_t y, uint16_t w, uint16_t h,
  225. const sw_matrix_t *matrix)
  226. {
  227. uint8_t * dst8 = dst;
  228. uint16_t dst_bytes_per_pixel = 3;
  229. uint16_t src_bytes_per_pixel = 2;
  230. int32_t src_coord_x = matrix->tx +
  231. y * matrix->shx + x * matrix->sx;
  232. int32_t src_coord_y = matrix->ty +
  233. y * matrix->sy + x * matrix->shy;
  234. for (int j = h; j > 0; j--) {
  235. int32_t p_x = src_coord_x;
  236. int32_t p_y = src_coord_y;
  237. uint8_t *tmp_dst = (uint8_t *)dst8;
  238. int x1 = 0, x2 = w - 1;
  239. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  240. p_x, p_y, matrix->sx, matrix->shy);
  241. if (x1 > x2) {
  242. goto next_line;
  243. } else if (x1 > 0) {
  244. p_x += matrix->sx * x1;
  245. p_y += matrix->shy * x1;
  246. tmp_dst += x1 * dst_bytes_per_pixel;
  247. }
  248. for (int i = x2 - x1; i >= 0; i--) {
  249. int x = FLOOR_FIXEDPOINT16(p_x);
  250. int y = FLOOR_FIXEDPOINT16(p_y);
  251. int x_frac = p_x - FIXEDPOINT16(x);
  252. int y_frac = p_y - FIXEDPOINT16(y);
  253. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  254. uint8_t *src2 = src1 + src_bytes_per_pixel;
  255. uint8_t *src3 = src1 + src_pitch;
  256. uint8_t *src4 = src2 + src_pitch;
  257. uint16_t c16;
  258. c16 = bilinear_rgb565_fast_m6(*(uint16_t*)src1,
  259. *(uint16_t*)src2, *(uint16_t*)src3, *(uint16_t*)src4,
  260. x_frac >> 10, y_frac >> 10, 6);
  261. *tmp_dst++ = ((c16 & 0x1f) << 3) | (c16 & 0x07);
  262. *tmp_dst++ = ((c16 & 0x07e0) >> 3) | ((c16 & 0x60) >> 5);
  263. *tmp_dst++ = ((c16 & 0xf800) >> 8) | ((c16 & 0x3800) >> 11);
  264. p_x += matrix->sx;
  265. p_y += matrix->shy;
  266. }
  267. next_line:
  268. src_coord_x += matrix->shx;
  269. src_coord_y += matrix->sy;
  270. dst8 += dst_pitch;
  271. }
  272. }
  273. void sw_transform_rgb565_over_argb8888(void *dst, const void *src,
  274. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  275. int16_t x, int16_t y, uint16_t w, uint16_t h,
  276. const sw_matrix_t *matrix)
  277. {
  278. //#ifdef CONFIG_GUI_API_BROM_LEOPARD
  279. // p_brom_libgui_api->p_sw_transform_rgb565_over_argb8888(
  280. // dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  281. //#else
  282. uint8_t * dst8 = dst;
  283. uint16_t src_bytes_per_pixel = 2;
  284. int32_t src_coord_x = matrix->tx +
  285. y * matrix->shx + x * matrix->sx;
  286. int32_t src_coord_y = matrix->ty +
  287. y * matrix->sy + x * matrix->shy;
  288. for (int j = h; j > 0; j--) {
  289. int32_t p_x = src_coord_x;
  290. int32_t p_y = src_coord_y;
  291. uint32_t *tmp_dst = (uint32_t *)dst8;
  292. int x1 = 0, x2 = w - 1;
  293. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  294. p_x, p_y, matrix->sx, matrix->shy);
  295. if (x1 > x2) {
  296. goto next_line;
  297. } else if (x1 > 0) {
  298. p_x += matrix->sx * x1;
  299. p_y += matrix->shy * x1;
  300. tmp_dst += x1;
  301. }
  302. for (int i = x2 - x1; i >= 0; i--) {
  303. int x = FLOOR_FIXEDPOINT16(p_x);
  304. int y = FLOOR_FIXEDPOINT16(p_y);
  305. int x_frac = p_x - FIXEDPOINT16(x);
  306. int y_frac = p_y - FIXEDPOINT16(y);
  307. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  308. uint8_t *src2 = src1 + src_bytes_per_pixel;
  309. uint8_t *src3 = src1 + src_pitch;
  310. uint8_t *src4 = src2 + src_pitch;
  311. uint16_t c16;
  312. c16 = bilinear_rgb565_fast_m6(*(uint16_t*)src1,
  313. *(uint16_t*)src2, *(uint16_t*)src3, *(uint16_t*)src4,
  314. x_frac >> 10, y_frac >> 10, 6);
  315. *tmp_dst = ((c16 & 0x1f) << 3) | (c16 & 0x07) |
  316. ((c16 & 0x07e0) << 5) | ((c16 & 0x60) << 3) |
  317. ((c16 & 0xf800) << 8) | ((c16 & 0x3800) << 5) | 0xFF000000;
  318. tmp_dst += 1;
  319. p_x += matrix->sx;
  320. p_y += matrix->shy;
  321. }
  322. next_line:
  323. src_coord_x += matrix->shx;
  324. src_coord_y += matrix->sy;
  325. dst8 += dst_pitch;
  326. }
  327. //#endif /* CONFIG_GUI_API_BROM_LEOPARD */
  328. }
  329. void sw_transform_rgb565a8_over_rgb565(void *dst, const void *src, const void *src_opa,
  330. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_opa_pitch,
  331. uint16_t src_w, uint16_t src_h, int16_t x, int16_t y, uint16_t w, uint16_t h,
  332. const sw_matrix_t *matrix)
  333. {
  334. uint8_t * dst8 = dst;
  335. uint16_t src_bytes_per_pixel = 2;
  336. int32_t src_coord_x = matrix->tx +
  337. y * matrix->shx + x * matrix->sx;
  338. int32_t src_coord_y = matrix->ty +
  339. y * matrix->sy + x * matrix->shy;
  340. for (int j = h; j > 0; j--) {
  341. int32_t p_x = src_coord_x;
  342. int32_t p_y = src_coord_y;
  343. uint16_t *tmp_dst = (uint16_t *)dst8;
  344. int x1 = 0, x2 = w - 1;
  345. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  346. p_x, p_y, matrix->sx, matrix->shy);
  347. if (x1 > x2) {
  348. goto next_line;
  349. } else if (x1 > 0) {
  350. p_x += matrix->sx * x1;
  351. p_y += matrix->shy * x1;
  352. tmp_dst += x1;
  353. }
  354. for (int i = x2 - x1; i >= 0; i--) {
  355. int x = FLOOR_FIXEDPOINT16(p_x);
  356. int y = FLOOR_FIXEDPOINT16(p_y);
  357. int x_frac = p_x - FIXEDPOINT16(x);
  358. int y_frac = p_y - FIXEDPOINT16(y);
  359. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  360. uint8_t *src2 = src1 + src_bytes_per_pixel;
  361. uint8_t *src3 = src1 + src_pitch;
  362. uint8_t *src4 = src2 + src_pitch;
  363. uint8_t *src_a1 = (uint8_t *)src_opa + y * src_opa_pitch + x;
  364. uint8_t *src_a2 = src1 + 1;
  365. uint8_t *src_a3 = src1 + src_opa_pitch;
  366. uint8_t *src_a4 = src2 + src_opa_pitch;
  367. sw_color16a8_t col24;
  368. col24.rgb = bilinear_rgb565_fast_m6(*(uint16_t*)src1,
  369. *(uint16_t*)src2, *(uint16_t*)src3, *(uint16_t*)src4,
  370. x_frac >> 10, y_frac >> 10, 6);
  371. col24.a = bilinear_a8_fast_m8(*src_a1, *src_a2, *src_a3, *src_a4,
  372. x_frac >> 8, y_frac >> 8, 8);
  373. *tmp_dst = blend_argb8565_over_rgb565(*tmp_dst, (uint8_t *)&col24);
  374. tmp_dst += 1;
  375. p_x += matrix->sx;
  376. p_y += matrix->shy;
  377. }
  378. next_line:
  379. src_coord_x += matrix->shx;
  380. src_coord_y += matrix->sy;
  381. dst8 += dst_pitch;
  382. }
  383. }
  384. void sw_transform_rgb565a8_over_rgb888(void *dst, const void *src, const void *src_opa,
  385. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_opa_pitch,
  386. uint16_t src_w, uint16_t src_h, int16_t x, int16_t y, uint16_t w, uint16_t h,
  387. const sw_matrix_t *matrix)
  388. {
  389. uint8_t * dst8 = dst;
  390. uint16_t dst_bytes_per_pixel = 3;
  391. uint16_t src_bytes_per_pixel = 2;
  392. int32_t src_coord_x = matrix->tx +
  393. y * matrix->shx + x * matrix->sx;
  394. int32_t src_coord_y = matrix->ty +
  395. y * matrix->sy + x * matrix->shy;
  396. for (int j = h; j > 0; j--) {
  397. int32_t p_x = src_coord_x;
  398. int32_t p_y = src_coord_y;
  399. uint8_t *tmp_dst = (uint8_t *)dst8;
  400. int x1 = 0, x2 = w - 1;
  401. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  402. p_x, p_y, matrix->sx, matrix->shy);
  403. if (x1 > x2) {
  404. goto next_line;
  405. } else if (x1 > 0) {
  406. p_x += matrix->sx * x1;
  407. p_y += matrix->shy * x1;
  408. tmp_dst += x1 * dst_bytes_per_pixel;
  409. }
  410. for (int i = x2 - x1; i >= 0; i--) {
  411. int x = FLOOR_FIXEDPOINT16(p_x);
  412. int y = FLOOR_FIXEDPOINT16(p_y);
  413. int x_frac = p_x - FIXEDPOINT16(x);
  414. int y_frac = p_y - FIXEDPOINT16(y);
  415. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  416. uint8_t *src2 = src1 + src_bytes_per_pixel;
  417. uint8_t *src3 = src1 + src_pitch;
  418. uint8_t *src4 = src2 + src_pitch;
  419. uint8_t *src_a1 = (uint8_t *)src_opa + y * src_opa_pitch + x;
  420. uint8_t *src_a2 = src1 + 1;
  421. uint8_t *src_a3 = src1 + src_opa_pitch;
  422. uint8_t *src_a4 = src2 + src_opa_pitch;
  423. sw_color32_t col32 = {
  424. .a = 255,
  425. .r = tmp_dst[2],
  426. .g = tmp_dst[1],
  427. .b = tmp_dst[0],
  428. };
  429. sw_color16a8_t col24;
  430. col24.rgb = bilinear_rgb565_fast_m6(*(uint16_t*)src1,
  431. *(uint16_t*)src2, *(uint16_t*)src3, *(uint16_t*)src4,
  432. x_frac >> 10, y_frac >> 10, 6);
  433. col24.a = bilinear_a8_fast_m8(*src_a1, *src_a2, *src_a3, *src_a4,
  434. x_frac >> 8, y_frac >> 8, 8);
  435. col32.full = blend_argb8565_over_argb8888(col32.full, (uint8_t *)&col24);
  436. *tmp_dst++ = col32.b;
  437. *tmp_dst++ = col32.g;
  438. *tmp_dst++ = col32.r;
  439. p_x += matrix->sx;
  440. p_y += matrix->shy;
  441. }
  442. next_line:
  443. src_coord_x += matrix->shx;
  444. src_coord_y += matrix->sy;
  445. dst8 += dst_pitch;
  446. }
  447. }
  448. void sw_transform_rgb565a8_over_argb8888(void *dst, const void *src, const void *src_opa,
  449. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_opa_pitch,
  450. uint16_t src_w, uint16_t src_h, int16_t x, int16_t y, uint16_t w, uint16_t h,
  451. const sw_matrix_t *matrix)
  452. {
  453. uint8_t * dst8 = dst;
  454. uint16_t src_bytes_per_pixel = 2;
  455. int32_t src_coord_x = matrix->tx +
  456. y * matrix->shx + x * matrix->sx;
  457. int32_t src_coord_y = matrix->ty +
  458. y * matrix->sy + x * matrix->shy;
  459. for (int j = h; j > 0; j--) {
  460. int32_t p_x = src_coord_x;
  461. int32_t p_y = src_coord_y;
  462. uint32_t *tmp_dst = (uint32_t *)dst8;
  463. int x1 = 0, x2 = w - 1;
  464. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  465. p_x, p_y, matrix->sx, matrix->shy);
  466. if (x1 > x2) {
  467. goto next_line;
  468. } else if (x1 > 0) {
  469. p_x += matrix->sx * x1;
  470. p_y += matrix->shy * x1;
  471. tmp_dst += x1;
  472. }
  473. for (int i = x2 - x1; i >= 0; i--) {
  474. int x = FLOOR_FIXEDPOINT16(p_x);
  475. int y = FLOOR_FIXEDPOINT16(p_y);
  476. int x_frac = p_x - FIXEDPOINT16(x);
  477. int y_frac = p_y - FIXEDPOINT16(y);
  478. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  479. uint8_t *src2 = src1 + src_bytes_per_pixel;
  480. uint8_t *src3 = src1 + src_pitch;
  481. uint8_t *src4 = src2 + src_pitch;
  482. uint8_t *src_a1 = (uint8_t *)src_opa + y * src_opa_pitch + x;
  483. uint8_t *src_a2 = src1 + 1;
  484. uint8_t *src_a3 = src1 + src_opa_pitch;
  485. uint8_t *src_a4 = src2 + src_opa_pitch;
  486. sw_color16a8_t col24;
  487. col24.rgb = bilinear_rgb565_fast_m6(*(uint16_t*)src1,
  488. *(uint16_t*)src2, *(uint16_t*)src3, *(uint16_t*)src4,
  489. x_frac >> 10, y_frac >> 10, 6);
  490. col24.a = bilinear_a8_fast_m8(*src_a1, *src_a2, *src_a3, *src_a4,
  491. x_frac >> 8, y_frac >> 8, 8);
  492. *tmp_dst = blend_argb8565_over_argb8888(*tmp_dst, (uint8_t *)&col24);
  493. tmp_dst += 1;
  494. p_x += matrix->sx;
  495. p_y += matrix->shy;
  496. }
  497. next_line:
  498. src_coord_x += matrix->shx;
  499. src_coord_y += matrix->sy;
  500. dst8 += dst_pitch;
  501. }
  502. }
  503. void sw_transform_argb8565_over_rgb565(void *dst, const void *src,
  504. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  505. int16_t x, int16_t y, uint16_t w, uint16_t h,
  506. const sw_matrix_t *matrix)
  507. {
  508. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  509. p_brom_libgui_api->p_sw_transform_argb8565_over_rgb565(
  510. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  511. #else
  512. uint8_t * dst8 = dst;
  513. uint16_t src_bytes_per_pixel = 3;
  514. int32_t src_coord_x = matrix->tx +
  515. y * matrix->shx + x * matrix->sx;
  516. int32_t src_coord_y = matrix->ty +
  517. y * matrix->sy + x * matrix->shy;
  518. for (int j = h; j > 0; j--) {
  519. int32_t p_x = src_coord_x;
  520. int32_t p_y = src_coord_y;
  521. uint16_t *tmp_dst = (uint16_t *)dst8;
  522. int x1 = 0, x2 = w - 1;
  523. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  524. p_x, p_y, matrix->sx, matrix->shy);
  525. if (x1 > x2) {
  526. goto next_line;
  527. } else if (x1 > 0) {
  528. p_x += matrix->sx * x1;
  529. p_y += matrix->shy * x1;
  530. tmp_dst += x1;
  531. }
  532. for (int i = x2 - x1; i >= 0; i--) {
  533. int x = FLOOR_FIXEDPOINT16(p_x);
  534. int y = FLOOR_FIXEDPOINT16(p_y);
  535. int x_frac = p_x - FIXEDPOINT16(x);
  536. int y_frac = p_y - FIXEDPOINT16(y);
  537. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  538. uint8_t *src2 = src1 + src_bytes_per_pixel;
  539. uint8_t *src3 = src1 + src_pitch;
  540. uint8_t *src4 = src2 + src_pitch;
  541. uint8_t result[3];
  542. bilinear_argb8565_fast_m6(result, src1, src2, src3, src4,
  543. x_frac >> 10, y_frac >> 10, 6);
  544. *tmp_dst = blend_argb8565_over_rgb565(*tmp_dst, result);
  545. tmp_dst += 1;
  546. p_x += matrix->sx;
  547. p_y += matrix->shy;
  548. }
  549. next_line:
  550. src_coord_x += matrix->shx;
  551. src_coord_y += matrix->sy;
  552. dst8 += dst_pitch;
  553. }
  554. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  555. }
  556. void sw_transform_argb8565_over_rgb888(void *dst, const void *src,
  557. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  558. int16_t x, int16_t y, uint16_t w, uint16_t h,
  559. const sw_matrix_t *matrix)
  560. {
  561. uint8_t * dst8 = dst;
  562. uint16_t dst_bytes_per_pixel = 3;
  563. uint16_t src_bytes_per_pixel = 3;
  564. int32_t src_coord_x = matrix->tx +
  565. y * matrix->shx + x * matrix->sx;
  566. int32_t src_coord_y = matrix->ty +
  567. y * matrix->sy + x * matrix->shy;
  568. for (int j = h; j > 0; j--) {
  569. int32_t p_x = src_coord_x;
  570. int32_t p_y = src_coord_y;
  571. uint8_t *tmp_dst = (uint8_t *)dst8;
  572. int x1 = 0, x2 = w - 1;
  573. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  574. p_x, p_y, matrix->sx, matrix->shy);
  575. if (x1 > x2) {
  576. goto next_line;
  577. } else if (x1 > 0) {
  578. p_x += matrix->sx * x1;
  579. p_y += matrix->shy * x1;
  580. tmp_dst += x1 * dst_bytes_per_pixel;
  581. }
  582. for (int i = x2 - x1; i >= 0; i--) {
  583. int x = FLOOR_FIXEDPOINT16(p_x);
  584. int y = FLOOR_FIXEDPOINT16(p_y);
  585. int x_frac = p_x - FIXEDPOINT16(x);
  586. int y_frac = p_y - FIXEDPOINT16(y);
  587. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  588. uint8_t *src2 = src1 + src_bytes_per_pixel;
  589. uint8_t *src3 = src1 + src_pitch;
  590. uint8_t *src4 = src2 + src_pitch;
  591. uint8_t result[3];
  592. sw_color32_t col32 = {
  593. .a = 255,
  594. .r = tmp_dst[2],
  595. .g = tmp_dst[1],
  596. .b = tmp_dst[0],
  597. };
  598. bilinear_argb8565_fast_m6(result, src1, src2, src3, src4,
  599. x_frac >> 10, y_frac >> 10, 6);
  600. col32.full = blend_argb8565_over_argb8888(col32.full, result);
  601. *tmp_dst++ = col32.b;
  602. *tmp_dst++ = col32.g;
  603. *tmp_dst++ = col32.r;
  604. p_x += matrix->sx;
  605. p_y += matrix->shy;
  606. }
  607. next_line:
  608. src_coord_x += matrix->shx;
  609. src_coord_y += matrix->sy;
  610. dst8 += dst_pitch;
  611. }
  612. }
  613. void sw_transform_argb8565_over_argb8888(void *dst, const void *src,
  614. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  615. int16_t x, int16_t y, uint16_t w, uint16_t h,
  616. const sw_matrix_t *matrix)
  617. {
  618. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  619. p_brom_libgui_api->p_sw_transform_argb8565_over_argb8888(
  620. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  621. #else
  622. uint8_t * dst8 = dst;
  623. uint16_t src_bytes_per_pixel = 3;
  624. int32_t src_coord_x = matrix->tx +
  625. y * matrix->shx + x * matrix->sx;
  626. int32_t src_coord_y = matrix->ty +
  627. y * matrix->sy + x * matrix->shy;
  628. for (int j = h; j > 0; j--) {
  629. int32_t p_x = src_coord_x;
  630. int32_t p_y = src_coord_y;
  631. uint32_t *tmp_dst = (uint32_t *)dst8;
  632. int x1 = 0, x2 = w - 1;
  633. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  634. p_x, p_y, matrix->sx, matrix->shy);
  635. if (x1 > x2) {
  636. goto next_line;
  637. } else if (x1 > 0) {
  638. p_x += matrix->sx * x1;
  639. p_y += matrix->shy * x1;
  640. tmp_dst += x1;
  641. }
  642. for (int i = x2 - x1; i >= 0; i--) {
  643. int x = FLOOR_FIXEDPOINT16(p_x);
  644. int y = FLOOR_FIXEDPOINT16(p_y);
  645. int x_frac = p_x - FIXEDPOINT16(x);
  646. int y_frac = p_y - FIXEDPOINT16(y);
  647. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  648. uint8_t *src2 = src1 + src_bytes_per_pixel;
  649. uint8_t *src3 = src1 + src_pitch;
  650. uint8_t *src4 = src2 + src_pitch;
  651. uint8_t result[3];
  652. bilinear_argb8565_fast_m6(result, src1, src2, src3, src4,
  653. x_frac >> 10, y_frac >> 10, 6);
  654. *tmp_dst = blend_argb8565_over_argb8888(*tmp_dst, result);
  655. tmp_dst += 1;
  656. p_x += matrix->sx;
  657. p_y += matrix->shy;
  658. }
  659. next_line:
  660. src_coord_x += matrix->shx;
  661. src_coord_y += matrix->sy;
  662. dst8 += dst_pitch;
  663. }
  664. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  665. }
  666. void sw_transform_argb6666_over_rgb565(void *dst, const void *src,
  667. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  668. int16_t x, int16_t y, uint16_t w, uint16_t h,
  669. const sw_matrix_t *matrix)
  670. {
  671. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  672. p_brom_libgui_api->p_sw_transform_argb6666_over_rgb565(
  673. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  674. #else
  675. uint8_t * dst8 = dst;
  676. uint16_t src_bytes_per_pixel = 3;
  677. int32_t src_coord_x = matrix->tx +
  678. y * matrix->shx + x * matrix->sx;
  679. int32_t src_coord_y = matrix->ty +
  680. y * matrix->sy + x * matrix->shy;
  681. for (int j = h; j > 0; j--) {
  682. int32_t p_x = src_coord_x;
  683. int32_t p_y = src_coord_y;
  684. uint16_t *tmp_dst = (uint16_t *)dst8;
  685. int x1 = 0, x2 = w - 1;
  686. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  687. p_x, p_y, matrix->sx, matrix->shy);
  688. if (x1 > x2) {
  689. goto next_line;
  690. } else if (x1 > 0) {
  691. p_x += matrix->sx * x1;
  692. p_y += matrix->shy * x1;
  693. tmp_dst += x1;
  694. }
  695. for (int i = x2 - x1; i >= 0; i--) {
  696. int x = FLOOR_FIXEDPOINT16(p_x);
  697. int y = FLOOR_FIXEDPOINT16(p_y);
  698. int x_frac = p_x - FIXEDPOINT16(x);
  699. int y_frac = p_y - FIXEDPOINT16(y);
  700. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  701. uint8_t *src2 = src1 + src_bytes_per_pixel;
  702. uint8_t *src3 = src1 + src_pitch;
  703. uint8_t *src4 = src2 + src_pitch;
  704. uint8_t result[3];
  705. bilinear_argb6666_fast_m6(result, src1, src2, src3, src4,
  706. x_frac >> 10, y_frac >> 10, 6);
  707. *tmp_dst = blend_argb6666_over_rgb565(*tmp_dst, result);
  708. tmp_dst += 1;
  709. p_x += matrix->sx;
  710. p_y += matrix->shy;
  711. }
  712. next_line:
  713. src_coord_x += matrix->shx;
  714. src_coord_y += matrix->sy;
  715. dst8 += dst_pitch;
  716. }
  717. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  718. }
  719. void sw_transform_argb6666_over_rgb888(void *dst, const void *src,
  720. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  721. int16_t x, int16_t y, uint16_t w, uint16_t h,
  722. const sw_matrix_t *matrix)
  723. {
  724. uint8_t * dst8 = dst;
  725. uint16_t dst_bytes_per_pixel = 3;
  726. uint16_t src_bytes_per_pixel = 3;
  727. int32_t src_coord_x = matrix->tx +
  728. y * matrix->shx + x * matrix->sx;
  729. int32_t src_coord_y = matrix->ty +
  730. y * matrix->sy + x * matrix->shy;
  731. for (int j = h; j > 0; j--) {
  732. int32_t p_x = src_coord_x;
  733. int32_t p_y = src_coord_y;
  734. uint8_t *tmp_dst = (uint8_t *)dst8;
  735. int x1 = 0, x2 = w - 1;
  736. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  737. p_x, p_y, matrix->sx, matrix->shy);
  738. if (x1 > x2) {
  739. goto next_line;
  740. } else if (x1 > 0) {
  741. p_x += matrix->sx * x1;
  742. p_y += matrix->shy * x1;
  743. tmp_dst += x1 * dst_bytes_per_pixel;
  744. }
  745. for (int i = x2 - x1; i >= 0; i--) {
  746. int x = FLOOR_FIXEDPOINT16(p_x);
  747. int y = FLOOR_FIXEDPOINT16(p_y);
  748. int x_frac = p_x - FIXEDPOINT16(x);
  749. int y_frac = p_y - FIXEDPOINT16(y);
  750. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  751. uint8_t *src2 = src1 + src_bytes_per_pixel;
  752. uint8_t *src3 = src1 + src_pitch;
  753. uint8_t *src4 = src2 + src_pitch;
  754. uint8_t result[3];
  755. sw_color32_t col32 = {
  756. .a = 255,
  757. .r = tmp_dst[2],
  758. .g = tmp_dst[1],
  759. .b = tmp_dst[0],
  760. };
  761. bilinear_argb6666_fast_m6(result, src1, src2, src3, src4,
  762. x_frac >> 10, y_frac >> 10, 6);
  763. col32.full = blend_argb6666_over_argb8888(col32.full, result);
  764. *tmp_dst++ = col32.b;
  765. *tmp_dst++ = col32.g;
  766. *tmp_dst++ = col32.r;
  767. p_x += matrix->sx;
  768. p_y += matrix->shy;
  769. }
  770. next_line:
  771. src_coord_x += matrix->shx;
  772. src_coord_y += matrix->sy;
  773. dst8 += dst_pitch;
  774. }
  775. }
  776. void sw_transform_argb6666_over_argb8888(void *dst, const void *src,
  777. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  778. int16_t x, int16_t y, uint16_t w, uint16_t h,
  779. const sw_matrix_t *matrix)
  780. {
  781. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  782. p_brom_libgui_api->p_sw_transform_argb6666_over_argb8888(
  783. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  784. #else
  785. uint8_t * dst8 = dst;
  786. uint16_t src_bytes_per_pixel = 3;
  787. int32_t src_coord_x = matrix->tx +
  788. y * matrix->shx + x * matrix->sx;
  789. int32_t src_coord_y = matrix->ty +
  790. y * matrix->sy + x * matrix->shy;
  791. for (int j = h; j > 0; j--) {
  792. int32_t p_x = src_coord_x;
  793. int32_t p_y = src_coord_y;
  794. uint32_t *tmp_dst = (uint32_t *)dst8;
  795. int x1 = 0, x2 = w - 1;
  796. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  797. p_x, p_y, matrix->sx, matrix->shy);
  798. if (x1 > x2) {
  799. goto next_line;
  800. } else if (x1 > 0) {
  801. p_x += matrix->sx * x1;
  802. p_y += matrix->shy * x1;
  803. tmp_dst += x1;
  804. }
  805. for (int i = x2 - x1; i >= 0; i--) {
  806. int x = FLOOR_FIXEDPOINT16(p_x);
  807. int y = FLOOR_FIXEDPOINT16(p_y);
  808. int x_frac = p_x - FIXEDPOINT16(x);
  809. int y_frac = p_y - FIXEDPOINT16(y);
  810. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  811. uint8_t *src2 = src1 + src_bytes_per_pixel;
  812. uint8_t *src3 = src1 + src_pitch;
  813. uint8_t *src4 = src2 + src_pitch;
  814. uint8_t result[3];
  815. bilinear_argb6666_fast_m6(result, src1, src2, src3, src4,
  816. x_frac >> 10, y_frac >> 10, 6);
  817. *tmp_dst = blend_argb6666_over_argb8888(*tmp_dst, result);
  818. tmp_dst += 1;
  819. p_x += matrix->sx;
  820. p_y += matrix->shy;
  821. }
  822. next_line:
  823. src_coord_x += matrix->shx;
  824. src_coord_y += matrix->sy;
  825. dst8 += dst_pitch;
  826. }
  827. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  828. }
  829. void sw_transform_argb8888_over_rgb565(void *dst, const void *src,
  830. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  831. int16_t x, int16_t y, uint16_t w, uint16_t h,
  832. const sw_matrix_t *matrix)
  833. {
  834. #ifdef CONFIG_GUI_API_BROM_LARK
  835. if (src_pitch == src_w * 4) {
  836. p_brom_libgui_api->p_sw_rotate_argb8888_over_rgb565(
  837. dst, src, dst_pitch / 2, src_w, src_h, x, y, w, h, matrix);
  838. return;
  839. }
  840. #endif
  841. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  842. p_brom_libgui_api->p_sw_transform_argb8888_over_rgb565(
  843. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  844. #else
  845. uint8_t * dst8 = dst;
  846. uint16_t src_bytes_per_pixel = 4;
  847. int32_t src_coord_x = matrix->tx +
  848. y * matrix->shx + x * matrix->sx;
  849. int32_t src_coord_y = matrix->ty +
  850. y * matrix->sy + x * matrix->shy;
  851. for (int j = h; j > 0; j--) {
  852. int32_t p_x = src_coord_x;
  853. int32_t p_y = src_coord_y;
  854. uint16_t *tmp_dst = (uint16_t *)dst8;
  855. int x1 = 0, x2 = w - 1;
  856. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  857. p_x, p_y, matrix->sx, matrix->shy);
  858. if (x1 > x2) {
  859. goto next_line;
  860. } else if (x1 > 0) {
  861. p_x += matrix->sx * x1;
  862. p_y += matrix->shy * x1;
  863. tmp_dst += x1;
  864. }
  865. for (int i = x2 - x1; i >= 0; i--) {
  866. int x = FLOOR_FIXEDPOINT16(p_x);
  867. int y = FLOOR_FIXEDPOINT16(p_y);
  868. int x_frac = p_x - FIXEDPOINT16(x);
  869. int y_frac = p_y - FIXEDPOINT16(y);
  870. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  871. uint8_t *src2 = src1 + src_bytes_per_pixel;
  872. uint8_t *src3 = src1 + src_pitch;
  873. uint8_t *src4 = src2 + src_pitch;
  874. uint32_t color = bilinear_argb8888_fast_m8(*(uint32_t*)src1,
  875. *(uint32_t*)src2, *(uint32_t*)src3, *(uint32_t*)src4,
  876. x_frac >> 8, y_frac >> 8, 8);
  877. *tmp_dst = blend_argb8888_over_rgb565(*tmp_dst, color);
  878. tmp_dst += 1;
  879. p_x += matrix->sx;
  880. p_y += matrix->shy;
  881. }
  882. next_line:
  883. src_coord_x += matrix->shx;
  884. src_coord_y += matrix->sy;
  885. dst8 += dst_pitch;
  886. }
  887. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  888. }
  889. void sw_transform_argb8888_over_rgb888(void *dst, const void *src,
  890. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  891. int16_t x, int16_t y, uint16_t w, uint16_t h,
  892. const sw_matrix_t *matrix)
  893. {
  894. uint8_t * dst8 = dst;
  895. uint16_t dst_bytes_per_pixel = 3;
  896. uint16_t src_bytes_per_pixel = 4;
  897. int32_t src_coord_x = matrix->tx +
  898. y * matrix->shx + x * matrix->sx;
  899. int32_t src_coord_y = matrix->ty +
  900. y * matrix->sy + x * matrix->shy;
  901. for (int j = h; j > 0; j--) {
  902. int32_t p_x = src_coord_x;
  903. int32_t p_y = src_coord_y;
  904. uint8_t *tmp_dst = (uint8_t *)dst8;
  905. int x1 = 0, x2 = w - 1;
  906. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  907. p_x, p_y, matrix->sx, matrix->shy);
  908. if (x1 > x2) {
  909. goto next_line;
  910. } else if (x1 > 0) {
  911. p_x += matrix->sx * x1;
  912. p_y += matrix->shy * x1;
  913. tmp_dst += x1 * dst_bytes_per_pixel;
  914. }
  915. for (int i = x2 - x1; i >= 0; i--) {
  916. int x = FLOOR_FIXEDPOINT16(p_x);
  917. int y = FLOOR_FIXEDPOINT16(p_y);
  918. int x_frac = p_x - FIXEDPOINT16(x);
  919. int y_frac = p_y - FIXEDPOINT16(y);
  920. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  921. uint8_t *src2 = src1 + src_bytes_per_pixel;
  922. uint8_t *src3 = src1 + src_pitch;
  923. uint8_t *src4 = src2 + src_pitch;
  924. sw_color32_t col32 = {
  925. .a = 255,
  926. .r = tmp_dst[2],
  927. .g = tmp_dst[1],
  928. .b = tmp_dst[0],
  929. };
  930. uint32_t color = bilinear_argb8888_fast_m8(*(uint32_t*)src1,
  931. *(uint32_t*)src2, *(uint32_t*)src3, *(uint32_t*)src4,
  932. x_frac >> 8, y_frac >> 8, 8);
  933. col32.full = blend_argb8888_over_argb8888(col32.full, color);
  934. *tmp_dst++ = col32.b;
  935. *tmp_dst++ = col32.g;
  936. *tmp_dst++ = col32.r;
  937. p_x += matrix->sx;
  938. p_y += matrix->shy;
  939. }
  940. next_line:
  941. src_coord_x += matrix->shx;
  942. src_coord_y += matrix->sy;
  943. dst8 += dst_pitch;
  944. }
  945. }
  946. void sw_transform_argb8888_over_argb8888(void *dst, const void *src,
  947. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  948. int16_t x, int16_t y, uint16_t w, uint16_t h,
  949. const sw_matrix_t *matrix)
  950. {
  951. #ifdef CONFIG_GUI_API_BROM_LARK
  952. if (src_pitch == src_w * 4) {
  953. p_brom_libgui_api->p_sw_rotate_argb8888_over_argb8888(
  954. dst, src, dst_pitch / 4, src_w, src_h, x, y, w, h, matrix);
  955. return;
  956. }
  957. #endif
  958. #ifdef CONFIG_GUI_API_BROM_LEOPARD
  959. p_brom_libgui_api->p_sw_transform_argb8888_over_argb8888(
  960. dst, src, dst_pitch, src_pitch, src_w, src_h, x, y, w, h, matrix);
  961. #else
  962. uint8_t * dst8 = dst;
  963. uint16_t src_bytes_per_pixel = 4;
  964. int32_t src_coord_x = matrix->tx +
  965. y * matrix->shx + x * matrix->sx;
  966. int32_t src_coord_y = matrix->ty +
  967. y * matrix->sy + x * matrix->shy;
  968. for (int j = h; j > 0; j--) {
  969. int32_t p_x = src_coord_x;
  970. int32_t p_y = src_coord_y;
  971. uint32_t *tmp_dst = (uint32_t *)dst8;
  972. int x1 = 0, x2 = w - 1;
  973. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  974. p_x, p_y, matrix->sx, matrix->shy);
  975. if (x1 > x2) {
  976. goto next_line;
  977. } else if (x1 > 0) {
  978. p_x += matrix->sx * x1;
  979. p_y += matrix->shy * x1;
  980. tmp_dst += x1;
  981. }
  982. for (int i = x2 - x1; i >= 0; i--) {
  983. int x = FLOOR_FIXEDPOINT16(p_x);
  984. int y = FLOOR_FIXEDPOINT16(p_y);
  985. int x_frac = p_x - FIXEDPOINT16(x);
  986. int y_frac = p_y - FIXEDPOINT16(y);
  987. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  988. uint8_t *src2 = src1 + src_bytes_per_pixel;
  989. uint8_t *src3 = src1 + src_pitch;
  990. uint8_t *src4 = src2 + src_pitch;
  991. uint32_t color = bilinear_argb8888_fast_m8(*(uint32_t*)src1,
  992. *(uint32_t*)src2, *(uint32_t*)src3, *(uint32_t*)src4,
  993. x_frac >> 8, y_frac >> 8, 8);
  994. *tmp_dst = blend_argb8888_over_argb8888(*tmp_dst, color);
  995. tmp_dst += 1;
  996. p_x += matrix->sx;
  997. p_y += matrix->shy;
  998. }
  999. next_line:
  1000. src_coord_x += matrix->shx;
  1001. src_coord_y += matrix->sy;
  1002. dst8 += dst_pitch;
  1003. }
  1004. #endif /* CONFIG_GUI_API_BROM_LEOPARD */
  1005. }
  1006. void sw_transform_xrgb8888_over_rgb565(void *dst, const void *src,
  1007. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1008. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1009. const sw_matrix_t *matrix)
  1010. {
  1011. uint8_t * dst8 = dst;
  1012. uint16_t src_bytes_per_pixel = 4;
  1013. int32_t src_coord_x = matrix->tx +
  1014. y * matrix->shx + x * matrix->sx;
  1015. int32_t src_coord_y = matrix->ty +
  1016. y * matrix->sy + x * matrix->shy;
  1017. for (int j = h; j > 0; j--) {
  1018. int32_t p_x = src_coord_x;
  1019. int32_t p_y = src_coord_y;
  1020. uint16_t *tmp_dst = (uint16_t *)dst8;
  1021. int x1 = 0, x2 = w - 1;
  1022. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1023. p_x, p_y, matrix->sx, matrix->shy);
  1024. if (x1 > x2) {
  1025. goto next_line;
  1026. } else if (x1 > 0) {
  1027. p_x += matrix->sx * x1;
  1028. p_y += matrix->shy * x1;
  1029. tmp_dst += x1;
  1030. }
  1031. for (int i = x2 - x1; i >= 0; i--) {
  1032. int x = FLOOR_FIXEDPOINT16(p_x);
  1033. int y = FLOOR_FIXEDPOINT16(p_y);
  1034. int x_frac = p_x - FIXEDPOINT16(x);
  1035. int y_frac = p_y - FIXEDPOINT16(y);
  1036. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1037. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1038. uint8_t *src3 = src1 + src_pitch;
  1039. uint8_t *src4 = src2 + src_pitch;
  1040. uint32_t color = bilinear_argb8888_fast_m8(*(uint32_t*)src1,
  1041. *(uint32_t*)src2, *(uint32_t*)src3, *(uint32_t*)src4,
  1042. x_frac >> 8, y_frac >> 8, 8);
  1043. *tmp_dst = ((color & 0xf80000) >> 8) | ((color & 0x00fc00) >> 5) |
  1044. ((color & 0x0000f8) >> 3);
  1045. tmp_dst += 1;
  1046. p_x += matrix->sx;
  1047. p_y += matrix->shy;
  1048. }
  1049. next_line:
  1050. src_coord_x += matrix->shx;
  1051. src_coord_y += matrix->sy;
  1052. dst8 += dst_pitch;
  1053. }
  1054. }
  1055. void sw_transform_xrgb8888_over_rgb888(void *dst, const void *src,
  1056. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1057. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1058. const sw_matrix_t *matrix)
  1059. {
  1060. uint8_t * dst8 = dst;
  1061. uint16_t dst_bytes_per_pixel = 3;
  1062. uint16_t src_bytes_per_pixel = 4;
  1063. int32_t src_coord_x = matrix->tx +
  1064. y * matrix->shx + x * matrix->sx;
  1065. int32_t src_coord_y = matrix->ty +
  1066. y * matrix->sy + x * matrix->shy;
  1067. for (int j = h; j > 0; j--) {
  1068. int32_t p_x = src_coord_x;
  1069. int32_t p_y = src_coord_y;
  1070. uint8_t *tmp_dst = (uint8_t *)dst8;
  1071. int x1 = 0, x2 = w - 1;
  1072. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1073. p_x, p_y, matrix->sx, matrix->shy);
  1074. if (x1 > x2) {
  1075. goto next_line;
  1076. } else if (x1 > 0) {
  1077. p_x += matrix->sx * x1;
  1078. p_y += matrix->shy * x1;
  1079. tmp_dst += x1 * dst_bytes_per_pixel;
  1080. }
  1081. for (int i = x2 - x1; i >= 0; i--) {
  1082. int x = FLOOR_FIXEDPOINT16(p_x);
  1083. int y = FLOOR_FIXEDPOINT16(p_y);
  1084. int x_frac = p_x - FIXEDPOINT16(x);
  1085. int y_frac = p_y - FIXEDPOINT16(y);
  1086. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1087. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1088. uint8_t *src3 = src1 + src_pitch;
  1089. uint8_t *src4 = src2 + src_pitch;
  1090. sw_color32_t col32;
  1091. col32.full = bilinear_argb8888_fast_m8(*(uint32_t*)src1,
  1092. *(uint32_t*)src2, *(uint32_t*)src3, *(uint32_t*)src4,
  1093. x_frac >> 8, y_frac >> 8, 8);
  1094. *tmp_dst++ = col32.b;
  1095. *tmp_dst++ = col32.g;
  1096. *tmp_dst++ = col32.r;
  1097. p_x += matrix->sx;
  1098. p_y += matrix->shy;
  1099. }
  1100. next_line:
  1101. src_coord_x += matrix->shx;
  1102. src_coord_y += matrix->sy;
  1103. dst8 += dst_pitch;
  1104. }
  1105. }
  1106. void sw_transform_xrgb8888_over_argb8888(void *dst, const void *src,
  1107. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1108. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1109. const sw_matrix_t *matrix)
  1110. {
  1111. uint8_t * dst8 = dst;
  1112. uint16_t src_bytes_per_pixel = 4;
  1113. int32_t src_coord_x = matrix->tx +
  1114. y * matrix->shx + x * matrix->sx;
  1115. int32_t src_coord_y = matrix->ty +
  1116. y * matrix->sy + x * matrix->shy;
  1117. for (int j = h; j > 0; j--) {
  1118. int32_t p_x = src_coord_x;
  1119. int32_t p_y = src_coord_y;
  1120. uint32_t *tmp_dst = (uint32_t *)dst8;
  1121. int x1 = 0, x2 = w - 1;
  1122. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1123. p_x, p_y, matrix->sx, matrix->shy);
  1124. if (x1 > x2) {
  1125. goto next_line;
  1126. } else if (x1 > 0) {
  1127. p_x += matrix->sx * x1;
  1128. p_y += matrix->shy * x1;
  1129. tmp_dst += x1;
  1130. }
  1131. for (int i = x2 - x1; i >= 0; i--) {
  1132. int x = FLOOR_FIXEDPOINT16(p_x);
  1133. int y = FLOOR_FIXEDPOINT16(p_y);
  1134. int x_frac = p_x - FIXEDPOINT16(x);
  1135. int y_frac = p_y - FIXEDPOINT16(y);
  1136. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1137. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1138. uint8_t *src3 = src1 + src_pitch;
  1139. uint8_t *src4 = src2 + src_pitch;
  1140. uint32_t color = bilinear_argb8888_fast_m8(*(uint32_t*)src1,
  1141. *(uint32_t*)src2, *(uint32_t*)src3, *(uint32_t*)src4,
  1142. x_frac >> 8, y_frac >> 8, 8);
  1143. *tmp_dst = color | 0xff000000;
  1144. tmp_dst += 1;
  1145. p_x += matrix->sx;
  1146. p_y += matrix->shy;
  1147. }
  1148. next_line:
  1149. src_coord_x += matrix->shx;
  1150. src_coord_y += matrix->sy;
  1151. dst8 += dst_pitch;
  1152. }
  1153. }
  1154. void sw_transform_rgb888_over_rgb565(void *dst, const void *src,
  1155. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1156. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1157. const sw_matrix_t *matrix)
  1158. {
  1159. uint8_t * dst8 = dst;
  1160. uint16_t src_bytes_per_pixel = 3;
  1161. int32_t src_coord_x = matrix->tx +
  1162. y * matrix->shx + x * matrix->sx;
  1163. int32_t src_coord_y = matrix->ty +
  1164. y * matrix->sy + x * matrix->shy;
  1165. for (int j = h; j > 0; j--) {
  1166. int32_t p_x = src_coord_x;
  1167. int32_t p_y = src_coord_y;
  1168. uint16_t *tmp_dst = (uint16_t *)dst8;
  1169. int x1 = 0, x2 = w - 1;
  1170. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1171. p_x, p_y, matrix->sx, matrix->shy);
  1172. if (x1 > x2) {
  1173. goto next_line;
  1174. } else if (x1 > 0) {
  1175. p_x += matrix->sx * x1;
  1176. p_y += matrix->shy * x1;
  1177. tmp_dst += x1;
  1178. }
  1179. for (int i = x2 - x1; i >= 0; i--) {
  1180. int x = FLOOR_FIXEDPOINT16(p_x);
  1181. int y = FLOOR_FIXEDPOINT16(p_y);
  1182. int x_frac = p_x - FIXEDPOINT16(x);
  1183. int y_frac = p_y - FIXEDPOINT16(y);
  1184. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1185. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1186. uint8_t *src3 = src1 + src_pitch;
  1187. uint8_t *src4 = src2 + src_pitch;
  1188. uint32_t color = bilinear_rgb888_fast_m8(src1,
  1189. src2, src3, src4, x_frac >> 8, y_frac >> 8, 8);
  1190. *tmp_dst = ((color & 0xf80000) >> 8) | ((color & 0x00fc00) >> 5) |
  1191. ((color & 0x0000f8) >> 3);
  1192. tmp_dst += 1;
  1193. p_x += matrix->sx;
  1194. p_y += matrix->shy;
  1195. }
  1196. next_line:
  1197. src_coord_x += matrix->shx;
  1198. src_coord_y += matrix->sy;
  1199. dst8 += dst_pitch;
  1200. }
  1201. }
  1202. void sw_transform_rgb888_over_rgb888(void *dst, const void *src,
  1203. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1204. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1205. const sw_matrix_t *matrix)
  1206. {
  1207. uint8_t * dst8 = dst;
  1208. uint16_t dst_bytes_per_pixel = 3;
  1209. uint16_t src_bytes_per_pixel = 3;
  1210. int32_t src_coord_x = matrix->tx +
  1211. y * matrix->shx + x * matrix->sx;
  1212. int32_t src_coord_y = matrix->ty +
  1213. y * matrix->sy + x * matrix->shy;
  1214. for (int j = h; j > 0; j--) {
  1215. int32_t p_x = src_coord_x;
  1216. int32_t p_y = src_coord_y;
  1217. uint8_t *tmp_dst = (uint8_t *)dst8;
  1218. int x1 = 0, x2 = w - 1;
  1219. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1220. p_x, p_y, matrix->sx, matrix->shy);
  1221. if (x1 > x2) {
  1222. goto next_line;
  1223. } else if (x1 > 0) {
  1224. p_x += matrix->sx * x1;
  1225. p_y += matrix->shy * x1;
  1226. tmp_dst += x1 * dst_bytes_per_pixel;
  1227. }
  1228. for (int i = x2 - x1; i >= 0; i--) {
  1229. int x = FLOOR_FIXEDPOINT16(p_x);
  1230. int y = FLOOR_FIXEDPOINT16(p_y);
  1231. int x_frac = p_x - FIXEDPOINT16(x);
  1232. int y_frac = p_y - FIXEDPOINT16(y);
  1233. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1234. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1235. uint8_t *src3 = src1 + src_pitch;
  1236. uint8_t *src4 = src2 + src_pitch;
  1237. sw_color32_t col32;
  1238. col32.full = bilinear_rgb888_fast_m8(src1,
  1239. src2, src3, src4, x_frac >> 8, y_frac >> 8, 8);
  1240. *tmp_dst++ = col32.b;
  1241. *tmp_dst++ = col32.g;
  1242. *tmp_dst++ = col32.r;
  1243. p_x += matrix->sx;
  1244. p_y += matrix->shy;
  1245. }
  1246. next_line:
  1247. src_coord_x += matrix->shx;
  1248. src_coord_y += matrix->sy;
  1249. dst8 += dst_pitch;
  1250. }
  1251. }
  1252. void sw_transform_rgb888_over_argb8888(void *dst, const void *src,
  1253. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1254. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1255. const sw_matrix_t *matrix)
  1256. {
  1257. uint8_t * dst8 = dst;
  1258. uint16_t src_bytes_per_pixel = 3;
  1259. int32_t src_coord_x = matrix->tx +
  1260. y * matrix->shx + x * matrix->sx;
  1261. int32_t src_coord_y = matrix->ty +
  1262. y * matrix->sy + x * matrix->shy;
  1263. for (int j = h; j > 0; j--) {
  1264. int32_t p_x = src_coord_x;
  1265. int32_t p_y = src_coord_y;
  1266. uint32_t *tmp_dst = (uint32_t *)dst8;
  1267. int x1 = 0, x2 = w - 1;
  1268. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1269. p_x, p_y, matrix->sx, matrix->shy);
  1270. if (x1 > x2) {
  1271. goto next_line;
  1272. } else if (x1 > 0) {
  1273. p_x += matrix->sx * x1;
  1274. p_y += matrix->shy * x1;
  1275. tmp_dst += x1;
  1276. }
  1277. for (int i = x2 - x1; i >= 0; i--) {
  1278. int x = FLOOR_FIXEDPOINT16(p_x);
  1279. int y = FLOOR_FIXEDPOINT16(p_y);
  1280. int x_frac = p_x - FIXEDPOINT16(x);
  1281. int y_frac = p_y - FIXEDPOINT16(y);
  1282. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1283. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1284. uint8_t *src3 = src1 + src_pitch;
  1285. uint8_t *src4 = src2 + src_pitch;
  1286. uint32_t color = bilinear_rgb888_fast_m8(src1,
  1287. src2, src3, src4, x_frac >> 8, y_frac >> 8, 8);
  1288. *tmp_dst = color | 0xff000000;
  1289. tmp_dst += 1;
  1290. p_x += matrix->sx;
  1291. p_y += matrix->shy;
  1292. }
  1293. next_line:
  1294. src_coord_x += matrix->shx;
  1295. src_coord_y += matrix->sy;
  1296. dst8 += dst_pitch;
  1297. }
  1298. }
  1299. void sw_transform_a8_over_rgb565(void *dst, const void *src, uint32_t src_color,
  1300. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1301. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1302. const sw_matrix_t *matrix)
  1303. {
  1304. uint8_t * dst8 = dst;
  1305. uint8_t src_opa = src_color >> 24;
  1306. uint16_t src_bytes_per_pixel = 1;
  1307. int32_t src_coord_x = matrix->tx +
  1308. y * matrix->shx + x * matrix->sx;
  1309. int32_t src_coord_y = matrix->ty +
  1310. y * matrix->sy + x * matrix->shy;
  1311. for (int j = h; j > 0; j--) {
  1312. int32_t p_x = src_coord_x;
  1313. int32_t p_y = src_coord_y;
  1314. uint16_t *tmp_dst = (uint16_t *)dst8;
  1315. int x1 = 0, x2 = w - 1;
  1316. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1317. p_x, p_y, matrix->sx, matrix->shy);
  1318. if (x1 > x2) {
  1319. goto next_line;
  1320. } else if (x1 > 0) {
  1321. p_x += matrix->sx * x1;
  1322. p_y += matrix->shy * x1;
  1323. tmp_dst += x1;
  1324. }
  1325. for (int i = x2 - x1; i >= 0; i--) {
  1326. int x = FLOOR_FIXEDPOINT16(p_x);
  1327. int y = FLOOR_FIXEDPOINT16(p_y);
  1328. int x_frac = p_x - FIXEDPOINT16(x);
  1329. int y_frac = p_y - FIXEDPOINT16(y);
  1330. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1331. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1332. uint8_t *src3 = src1 + src_pitch;
  1333. uint8_t *src4 = src2 + src_pitch;
  1334. uint32_t opa = bilinear_a8_fast_m8(*src1,
  1335. *src2, *src3, *src4, x_frac >> 8, y_frac >> 8, 8);
  1336. if (src_opa < 255)
  1337. opa = (opa * src_opa) >> 8;
  1338. src_color = (src_color & 0xffffff) | (opa << 24);
  1339. *tmp_dst = blend_argb8888_over_rgb565(*tmp_dst, src_color);
  1340. tmp_dst += 1;
  1341. p_x += matrix->sx;
  1342. p_y += matrix->shy;
  1343. }
  1344. next_line:
  1345. src_coord_x += matrix->shx;
  1346. src_coord_y += matrix->sy;
  1347. dst8 += dst_pitch;
  1348. }
  1349. }
  1350. void sw_transform_a8_over_rgb888(void *dst, const void *src, uint32_t src_color,
  1351. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1352. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1353. const sw_matrix_t *matrix)
  1354. {
  1355. uint8_t * dst8 = dst;
  1356. uint16_t dst_bytes_per_pixel = 3;
  1357. uint8_t src_opa = src_color >> 24;
  1358. uint16_t src_bytes_per_pixel = 1;
  1359. int32_t src_coord_x = matrix->tx +
  1360. y * matrix->shx + x * matrix->sx;
  1361. int32_t src_coord_y = matrix->ty +
  1362. y * matrix->sy + x * matrix->shy;
  1363. for (int j = h; j > 0; j--) {
  1364. int32_t p_x = src_coord_x;
  1365. int32_t p_y = src_coord_y;
  1366. uint8_t *tmp_dst = (uint8_t *)dst8;
  1367. int x1 = 0, x2 = w - 1;
  1368. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1369. p_x, p_y, matrix->sx, matrix->shy);
  1370. if (x1 > x2) {
  1371. goto next_line;
  1372. } else if (x1 > 0) {
  1373. p_x += matrix->sx * x1;
  1374. p_y += matrix->shy * x1;
  1375. tmp_dst += x1 * dst_bytes_per_pixel;
  1376. }
  1377. for (int i = x2 - x1; i >= 0; i--) {
  1378. int x = FLOOR_FIXEDPOINT16(p_x);
  1379. int y = FLOOR_FIXEDPOINT16(p_y);
  1380. int x_frac = p_x - FIXEDPOINT16(x);
  1381. int y_frac = p_y - FIXEDPOINT16(y);
  1382. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1383. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1384. uint8_t *src3 = src1 + src_pitch;
  1385. uint8_t *src4 = src2 + src_pitch;
  1386. sw_color32_t col32 = {
  1387. .a = 255,
  1388. .r = tmp_dst[2],
  1389. .g = tmp_dst[1],
  1390. .b = tmp_dst[0],
  1391. };
  1392. uint32_t opa = bilinear_a8_fast_m8(*src1,
  1393. *src2, *src3, *src4, x_frac >> 8, y_frac >> 8, 8);
  1394. if (src_opa < 255)
  1395. opa = (opa * src_opa) >> 8;
  1396. src_color = (src_color & 0xffffff) | (opa << 24);
  1397. col32.full = blend_argb8888_over_argb8888(col32.full, src_color);
  1398. *tmp_dst++ = col32.b;
  1399. *tmp_dst++ = col32.g;
  1400. *tmp_dst++ = col32.r;
  1401. p_x += matrix->sx;
  1402. p_y += matrix->shy;
  1403. }
  1404. next_line:
  1405. src_coord_x += matrix->shx;
  1406. src_coord_y += matrix->sy;
  1407. dst8 += dst_pitch;
  1408. }
  1409. }
  1410. void sw_transform_a8_over_argb8888(void *dst, const void *src, uint32_t src_color,
  1411. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1412. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1413. const sw_matrix_t *matrix)
  1414. {
  1415. uint8_t * dst8 = dst;
  1416. uint8_t src_opa = src_color >> 24;
  1417. uint16_t src_bytes_per_pixel = 1;
  1418. int32_t src_coord_x = matrix->tx +
  1419. y * matrix->shx + x * matrix->sx;
  1420. int32_t src_coord_y = matrix->ty +
  1421. y * matrix->sy + x * matrix->shy;
  1422. for (int j = h; j > 0; j--) {
  1423. int32_t p_x = src_coord_x;
  1424. int32_t p_y = src_coord_y;
  1425. uint32_t *tmp_dst = (uint32_t *)dst8;
  1426. int x1 = 0, x2 = w - 1;
  1427. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1428. p_x, p_y, matrix->sx, matrix->shy);
  1429. if (x1 > x2) {
  1430. goto next_line;
  1431. } else if (x1 > 0) {
  1432. p_x += matrix->sx * x1;
  1433. p_y += matrix->shy * x1;
  1434. tmp_dst += x1;
  1435. }
  1436. for (int i = x2 - x1; i >= 0; i--) {
  1437. int x = FLOOR_FIXEDPOINT16(p_x);
  1438. int y = FLOOR_FIXEDPOINT16(p_y);
  1439. int x_frac = p_x - FIXEDPOINT16(x);
  1440. int y_frac = p_y - FIXEDPOINT16(y);
  1441. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1442. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1443. uint8_t *src3 = src1 + src_pitch;
  1444. uint8_t *src4 = src2 + src_pitch;
  1445. uint32_t opa = bilinear_a8_fast_m8(*src1,
  1446. *src2, *src3, *src4, x_frac >> 8, y_frac >> 8, 8);
  1447. if (src_opa < 255)
  1448. opa = (opa * src_opa) >> 8;
  1449. src_color = (src_color & 0xffffff) | (opa << 24);
  1450. *tmp_dst = blend_argb8888_over_argb8888(*tmp_dst, src_color);
  1451. tmp_dst += 1;
  1452. p_x += matrix->sx;
  1453. p_y += matrix->shy;
  1454. }
  1455. next_line:
  1456. src_coord_x += matrix->shx;
  1457. src_coord_y += matrix->sy;
  1458. dst8 += dst_pitch;
  1459. }
  1460. }
  1461. void sw_transform_index8_over_rgb565(void *dst, const void *src, const uint32_t *src_clut,
  1462. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1463. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1464. const sw_matrix_t *matrix)
  1465. {
  1466. uint8_t * dst8 = dst;
  1467. uint16_t src_bytes_per_pixel = 1;
  1468. int32_t src_coord_x = matrix->tx +
  1469. y * matrix->shx + x * matrix->sx;
  1470. int32_t src_coord_y = matrix->ty +
  1471. y * matrix->sy + x * matrix->shy;
  1472. for (int j = h; j > 0; j--) {
  1473. int32_t p_x = src_coord_x;
  1474. int32_t p_y = src_coord_y;
  1475. uint16_t *tmp_dst = (uint16_t *)dst8;
  1476. int x1 = 0, x2 = w - 1;
  1477. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1478. p_x, p_y, matrix->sx, matrix->shy);
  1479. if (x1 > x2) {
  1480. goto next_line;
  1481. } else if (x1 > 0) {
  1482. p_x += matrix->sx * x1;
  1483. p_y += matrix->shy * x1;
  1484. tmp_dst += x1;
  1485. }
  1486. for (int i = x2 - x1; i >= 0; i--) {
  1487. int x = FLOOR_FIXEDPOINT16(p_x);
  1488. int y = FLOOR_FIXEDPOINT16(p_y);
  1489. int x_frac = p_x - FIXEDPOINT16(x);
  1490. int y_frac = p_y - FIXEDPOINT16(y);
  1491. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1492. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1493. uint8_t *src3 = src1 + src_pitch;
  1494. uint8_t *src4 = src2 + src_pitch;
  1495. uint32_t color = bilinear_argb8888_fast_m8(src_clut[*src1],
  1496. src_clut[*src2], src_clut[*src3], src_clut[*src4],
  1497. x_frac >> 8, y_frac >> 8, 8);
  1498. *tmp_dst = blend_argb8888_over_rgb565(*tmp_dst, color);
  1499. tmp_dst += 1;
  1500. p_x += matrix->sx;
  1501. p_y += matrix->shy;
  1502. }
  1503. next_line:
  1504. src_coord_x += matrix->shx;
  1505. src_coord_y += matrix->sy;
  1506. dst8 += dst_pitch;
  1507. }
  1508. }
  1509. void sw_transform_index8_over_rgb888(void *dst, const void *src, const uint32_t *src_clut,
  1510. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1511. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1512. const sw_matrix_t *matrix)
  1513. {
  1514. uint8_t * dst8 = dst;
  1515. uint16_t dst_bytes_per_pixel = 3;
  1516. uint16_t src_bytes_per_pixel = 1;
  1517. int32_t src_coord_x = matrix->tx +
  1518. y * matrix->shx + x * matrix->sx;
  1519. int32_t src_coord_y = matrix->ty +
  1520. y * matrix->sy + x * matrix->shy;
  1521. for (int j = h; j > 0; j--) {
  1522. int32_t p_x = src_coord_x;
  1523. int32_t p_y = src_coord_y;
  1524. uint8_t *tmp_dst = (uint8_t *)dst8;
  1525. int x1 = 0, x2 = w - 1;
  1526. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1527. p_x, p_y, matrix->sx, matrix->shy);
  1528. if (x1 > x2) {
  1529. goto next_line;
  1530. } else if (x1 > 0) {
  1531. p_x += matrix->sx * x1;
  1532. p_y += matrix->shy * x1;
  1533. tmp_dst += x1 * dst_bytes_per_pixel;
  1534. }
  1535. for (int i = x2 - x1; i >= 0; i--) {
  1536. int x = FLOOR_FIXEDPOINT16(p_x);
  1537. int y = FLOOR_FIXEDPOINT16(p_y);
  1538. int x_frac = p_x - FIXEDPOINT16(x);
  1539. int y_frac = p_y - FIXEDPOINT16(y);
  1540. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1541. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1542. uint8_t *src3 = src1 + src_pitch;
  1543. uint8_t *src4 = src2 + src_pitch;
  1544. sw_color32_t col32 = {
  1545. .a = 255,
  1546. .r = tmp_dst[2],
  1547. .g = tmp_dst[1],
  1548. .b = tmp_dst[0],
  1549. };
  1550. uint32_t color = bilinear_argb8888_fast_m8(src_clut[*src1],
  1551. src_clut[*src2], src_clut[*src3], src_clut[*src4],
  1552. x_frac >> 8, y_frac >> 8, 8);
  1553. col32.full = blend_argb8888_over_argb8888(col32.full, color);
  1554. *tmp_dst++ = col32.b;
  1555. *tmp_dst++ = col32.g;
  1556. *tmp_dst++ = col32.r;
  1557. p_x += matrix->sx;
  1558. p_y += matrix->shy;
  1559. }
  1560. next_line:
  1561. src_coord_x += matrix->shx;
  1562. src_coord_y += matrix->sy;
  1563. dst8 += dst_pitch;
  1564. }
  1565. }
  1566. void sw_transform_index8_over_argb8888(void *dst, const void *src, const uint32_t *src_clut,
  1567. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1568. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1569. const sw_matrix_t *matrix)
  1570. {
  1571. uint8_t * dst8 = dst;
  1572. uint16_t src_bytes_per_pixel = 1;
  1573. int32_t src_coord_x = matrix->tx +
  1574. y * matrix->shx + x * matrix->sx;
  1575. int32_t src_coord_y = matrix->ty +
  1576. y * matrix->sy + x * matrix->shy;
  1577. for (int j = h; j > 0; j--) {
  1578. int32_t p_x = src_coord_x;
  1579. int32_t p_y = src_coord_y;
  1580. uint32_t *tmp_dst = (uint32_t *)dst8;
  1581. int x1 = 0, x2 = w - 1;
  1582. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1583. p_x, p_y, matrix->sx, matrix->shy);
  1584. if (x1 > x2) {
  1585. goto next_line;
  1586. } else if (x1 > 0) {
  1587. p_x += matrix->sx * x1;
  1588. p_y += matrix->shy * x1;
  1589. tmp_dst += x1;
  1590. }
  1591. for (int i = x2 - x1; i >= 0; i--) {
  1592. int x = FLOOR_FIXEDPOINT16(p_x);
  1593. int y = FLOOR_FIXEDPOINT16(p_y);
  1594. int x_frac = p_x - FIXEDPOINT16(x);
  1595. int y_frac = p_y - FIXEDPOINT16(y);
  1596. uint8_t *src1 = (uint8_t *)src + y * src_pitch + x * src_bytes_per_pixel;
  1597. uint8_t *src2 = src1 + src_bytes_per_pixel;
  1598. uint8_t *src3 = src1 + src_pitch;
  1599. uint8_t *src4 = src2 + src_pitch;
  1600. uint32_t color = bilinear_argb8888_fast_m8(src_clut[*src1],
  1601. src_clut[*src2], src_clut[*src3], src_clut[*src4],
  1602. x_frac >> 8, y_frac >> 8, 8);
  1603. *tmp_dst = blend_argb8888_over_argb8888(*tmp_dst, color);
  1604. tmp_dst += 1;
  1605. p_x += matrix->sx;
  1606. p_y += matrix->shy;
  1607. }
  1608. next_line:
  1609. src_coord_x += matrix->shx;
  1610. src_coord_y += matrix->sy;
  1611. dst8 += dst_pitch;
  1612. }
  1613. }
  1614. static void sw_transform_index124_over_rgb565(
  1615. void *dst, const void *src, const uint32_t *src_clut,
  1616. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1617. uint8_t src_bpp, int16_t x, int16_t y, uint16_t w, uint16_t h,
  1618. const sw_matrix_t *matrix)
  1619. {
  1620. uint8_t * dst8 = dst;
  1621. int32_t src_coord_x = matrix->tx +
  1622. y * matrix->shx + x * matrix->sx;
  1623. int32_t src_coord_y = matrix->ty +
  1624. y * matrix->sy + x * matrix->shy;
  1625. const uint8_t src_bmask = (1 << src_bpp) - 1;
  1626. const uint8_t src_bofs_max = 8 - src_bpp;
  1627. for (int j = h; j > 0; j--) {
  1628. int32_t p_x = src_coord_x;
  1629. int32_t p_y = src_coord_y;
  1630. uint16_t *tmp_dst = (uint16_t *)dst8;
  1631. int x1 = 0, x2 = w - 1;
  1632. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1633. p_x, p_y, matrix->sx, matrix->shy);
  1634. if (x1 > x2) {
  1635. goto next_line;
  1636. } else if (x1 > 0) {
  1637. p_x += matrix->sx * x1;
  1638. p_y += matrix->shy * x1;
  1639. tmp_dst += x1;
  1640. }
  1641. for (int i = x2 - x1; i >= 0; i--) {
  1642. int x = FLOOR_FIXEDPOINT16(p_x);
  1643. int y = FLOOR_FIXEDPOINT16(p_y);
  1644. int x_frac = p_x - FIXEDPOINT16(x);
  1645. int y_frac = p_y - FIXEDPOINT16(y);
  1646. uint16_t x_ofs1 = x * src_bpp;
  1647. uint16_t x_ofs2 = x * src_bpp + src_bpp;
  1648. uint8_t *src1 = (uint8_t *)src + y * src_pitch + (x_ofs1 >> 3);
  1649. uint8_t *src2 = (uint8_t *)src + y * src_pitch + (x_ofs2 >> 3);
  1650. uint8_t *src3 = src1 + src_pitch;
  1651. uint8_t *src4 = src2 + src_pitch;
  1652. x_ofs1 = src_bofs_max - (x_ofs1 & 0x7);
  1653. x_ofs2 = src_bofs_max - (x_ofs2 & 0x7);
  1654. uint8_t src1_idx = (*src1 >> x_ofs1) & src_bmask;
  1655. uint8_t src2_idx = (*src2 >> x_ofs2) & src_bmask;
  1656. uint8_t src3_idx = (*src3 >> x_ofs1) & src_bmask;
  1657. uint8_t src4_idx = (*src4 >> x_ofs2) & src_bmask;
  1658. uint32_t color = bilinear_argb8888_fast_m8(src_clut[src1_idx],
  1659. src_clut[src2_idx], src_clut[src3_idx], src_clut[src4_idx],
  1660. x_frac >> 8, y_frac >> 8, 8);
  1661. *tmp_dst = blend_argb8888_over_rgb565(*tmp_dst, color);
  1662. tmp_dst += 1;
  1663. p_x += matrix->sx;
  1664. p_y += matrix->shy;
  1665. }
  1666. next_line:
  1667. src_coord_x += matrix->shx;
  1668. src_coord_y += matrix->sy;
  1669. dst8 += dst_pitch;
  1670. }
  1671. }
  1672. static void sw_transform_index124_over_rgb888(
  1673. void *dst, const void *src, const uint32_t *src_clut,
  1674. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1675. uint8_t src_bpp, int16_t x, int16_t y, uint16_t w, uint16_t h,
  1676. const sw_matrix_t *matrix)
  1677. {
  1678. uint8_t * dst8 = dst;
  1679. uint16_t dst_bytes_per_pixel = 3;
  1680. int32_t src_coord_x = matrix->tx +
  1681. y * matrix->shx + x * matrix->sx;
  1682. int32_t src_coord_y = matrix->ty +
  1683. y * matrix->sy + x * matrix->shy;
  1684. const uint8_t src_bmask = (1 << src_bpp) - 1;
  1685. const uint8_t src_bofs_max = 8 - src_bpp;
  1686. for (int j = h; j > 0; j--) {
  1687. int32_t p_x = src_coord_x;
  1688. int32_t p_y = src_coord_y;
  1689. uint8_t *tmp_dst = (uint8_t *)dst8;
  1690. int x1 = 0, x2 = w - 1;
  1691. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1692. p_x, p_y, matrix->sx, matrix->shy);
  1693. if (x1 > x2) {
  1694. goto next_line;
  1695. } else if (x1 > 0) {
  1696. p_x += matrix->sx * x1;
  1697. p_y += matrix->shy * x1;
  1698. tmp_dst += x1 * dst_bytes_per_pixel;
  1699. }
  1700. for (int i = x2 - x1; i >= 0; i--) {
  1701. int x = FLOOR_FIXEDPOINT16(p_x);
  1702. int y = FLOOR_FIXEDPOINT16(p_y);
  1703. int x_frac = p_x - FIXEDPOINT16(x);
  1704. int y_frac = p_y - FIXEDPOINT16(y);
  1705. uint16_t x_ofs1 = x * src_bpp;
  1706. uint16_t x_ofs2 = x * src_bpp + src_bpp;
  1707. uint8_t *src1 = (uint8_t *)src + y * src_pitch + (x_ofs1 >> 3);
  1708. uint8_t *src2 = (uint8_t *)src + y * src_pitch + (x_ofs2 >> 3);
  1709. uint8_t *src3 = src1 + src_pitch;
  1710. uint8_t *src4 = src2 + src_pitch;
  1711. x_ofs1 = src_bofs_max - (x_ofs1 & 0x7);
  1712. x_ofs2 = src_bofs_max - (x_ofs2 & 0x7);
  1713. uint8_t src1_idx = (*src1 >> x_ofs1) & src_bmask;
  1714. uint8_t src2_idx = (*src2 >> x_ofs2) & src_bmask;
  1715. uint8_t src3_idx = (*src3 >> x_ofs1) & src_bmask;
  1716. uint8_t src4_idx = (*src4 >> x_ofs2) & src_bmask;
  1717. sw_color32_t col32 = {
  1718. .a = 255,
  1719. .r = tmp_dst[2],
  1720. .g = tmp_dst[1],
  1721. .b = tmp_dst[0],
  1722. };
  1723. uint32_t color = bilinear_argb8888_fast_m8(src_clut[src1_idx],
  1724. src_clut[src2_idx], src_clut[src3_idx], src_clut[src4_idx],
  1725. x_frac >> 8, y_frac >> 8, 8);
  1726. col32.full = blend_argb8888_over_argb8888(col32.full, color);
  1727. *tmp_dst++ = col32.b;
  1728. *tmp_dst++ = col32.g;
  1729. *tmp_dst++ = col32.r;
  1730. p_x += matrix->sx;
  1731. p_y += matrix->shy;
  1732. }
  1733. next_line:
  1734. src_coord_x += matrix->shx;
  1735. src_coord_y += matrix->sy;
  1736. dst8 += dst_pitch;
  1737. }
  1738. }
  1739. static void sw_transform_index124_over_argb8888(
  1740. void *dst, const void *src, const uint32_t *src_clut,
  1741. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1742. uint8_t src_bpp, int16_t x, int16_t y, uint16_t w, uint16_t h,
  1743. const sw_matrix_t *matrix)
  1744. {
  1745. uint8_t * dst8 = dst;
  1746. int32_t src_coord_x = matrix->tx +
  1747. y * matrix->shx + x * matrix->sx;
  1748. int32_t src_coord_y = matrix->ty +
  1749. y * matrix->sy + x * matrix->shy;
  1750. const uint8_t src_bmask = (1 << src_bpp) - 1;
  1751. const uint8_t src_bofs_max = 8 - src_bpp;
  1752. for (int j = h; j > 0; j--) {
  1753. int32_t p_x = src_coord_x;
  1754. int32_t p_y = src_coord_y;
  1755. uint32_t *tmp_dst = (uint32_t *)dst8;
  1756. int x1 = 0, x2 = w - 1;
  1757. sw_transform_compoute_x_range(&x1, &x2, src_w, src_h,
  1758. p_x, p_y, matrix->sx, matrix->shy);
  1759. if (x1 > x2) {
  1760. goto next_line;
  1761. } else if (x1 > 0) {
  1762. p_x += matrix->sx * x1;
  1763. p_y += matrix->shy * x1;
  1764. tmp_dst += x1;
  1765. }
  1766. for (int i = x2 - x1; i >= 0; i--) {
  1767. int x = FLOOR_FIXEDPOINT16(p_x);
  1768. int y = FLOOR_FIXEDPOINT16(p_y);
  1769. int x_frac = p_x - FIXEDPOINT16(x);
  1770. int y_frac = p_y - FIXEDPOINT16(y);
  1771. uint16_t x_ofs1 = x * src_bpp;
  1772. uint16_t x_ofs2 = x * src_bpp + src_bpp;
  1773. uint8_t *src1 = (uint8_t *)src + y * src_pitch + (x_ofs1 >> 3);
  1774. uint8_t *src2 = (uint8_t *)src + y * src_pitch + (x_ofs2 >> 3);
  1775. uint8_t *src3 = src1 + src_pitch;
  1776. uint8_t *src4 = src2 + src_pitch;
  1777. x_ofs1 = src_bofs_max - (x_ofs1 & 0x7);
  1778. x_ofs2 = src_bofs_max - (x_ofs2 & 0x7);
  1779. uint8_t src1_idx = (*src1 >> x_ofs1) & src_bmask;
  1780. uint8_t src2_idx = (*src2 >> x_ofs2) & src_bmask;
  1781. uint8_t src3_idx = (*src3 >> x_ofs1) & src_bmask;
  1782. uint8_t src4_idx = (*src4 >> x_ofs2) & src_bmask;
  1783. uint32_t color = bilinear_argb8888_fast_m8(src_clut[src1_idx],
  1784. src_clut[src2_idx], src_clut[src3_idx], src_clut[src4_idx],
  1785. x_frac >> 8, y_frac >> 8, 8);
  1786. *tmp_dst = blend_argb8888_over_argb8888(*tmp_dst, color);
  1787. tmp_dst += 1;
  1788. p_x += matrix->sx;
  1789. p_y += matrix->shy;
  1790. }
  1791. next_line:
  1792. src_coord_x += matrix->shx;
  1793. src_coord_y += matrix->sy;
  1794. dst8 += dst_pitch;
  1795. }
  1796. }
  1797. void sw_transform_index4_over_rgb565(
  1798. void *dst, const void *src, const uint32_t *src_clut,
  1799. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1800. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1801. const sw_matrix_t *matrix)
  1802. {
  1803. sw_transform_index124_over_rgb565(dst, src, src_clut, dst_pitch, src_pitch,
  1804. src_w, src_h, 4, x, y, w, h, matrix);
  1805. }
  1806. void sw_transform_index4_over_rgb888(
  1807. void *dst, const void *src, const uint32_t *src_clut,
  1808. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1809. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1810. const sw_matrix_t *matrix)
  1811. {
  1812. sw_transform_index124_over_rgb888(dst, src, src_clut, dst_pitch, src_pitch,
  1813. src_w, src_h, 4, x, y, w, h, matrix);
  1814. }
  1815. void sw_transform_index4_over_argb8888(
  1816. void *dst, const void *src, const uint32_t *src_clut,
  1817. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1818. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1819. const sw_matrix_t *matrix)
  1820. {
  1821. sw_transform_index124_over_argb8888(dst, src, src_clut, dst_pitch, src_pitch,
  1822. src_w, src_h, 4, x, y, w, h, matrix);
  1823. }
  1824. void sw_transform_index2_over_rgb565(
  1825. void *dst, const void *src, const uint32_t *src_clut,
  1826. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1827. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1828. const sw_matrix_t *matrix)
  1829. {
  1830. sw_transform_index124_over_rgb565(dst, src, src_clut, dst_pitch, src_pitch,
  1831. src_w, src_h, 2, x, y, w, h, matrix);
  1832. }
  1833. void sw_transform_index2_over_rgb888(
  1834. void *dst, const void *src, const uint32_t *src_clut,
  1835. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1836. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1837. const sw_matrix_t *matrix)
  1838. {
  1839. sw_transform_index124_over_rgb888(dst, src, src_clut, dst_pitch, src_pitch,
  1840. src_w, src_h, 2, x, y, w, h, matrix);
  1841. }
  1842. void sw_transform_index2_over_argb8888(
  1843. void *dst, const void *src, const uint32_t *src_clut,
  1844. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1845. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1846. const sw_matrix_t *matrix)
  1847. {
  1848. sw_transform_index124_over_argb8888(dst, src, src_clut, dst_pitch, src_pitch,
  1849. src_w, src_h, 2, x, y, w, h, matrix);
  1850. }
  1851. void sw_transform_index1_over_rgb565(
  1852. void *dst, const void *src, const uint32_t *src_clut,
  1853. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1854. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1855. const sw_matrix_t *matrix)
  1856. {
  1857. sw_transform_index124_over_rgb565(dst, src, src_clut, dst_pitch, src_pitch,
  1858. src_w, src_h, 1, x, y, w, h, matrix);
  1859. }
  1860. void sw_transform_index1_over_rgb888(
  1861. void *dst, const void *src, const uint32_t *src_clut,
  1862. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1863. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1864. const sw_matrix_t *matrix)
  1865. {
  1866. sw_transform_index124_over_rgb888(dst, src, src_clut, dst_pitch, src_pitch,
  1867. src_w, src_h, 1, x, y, w, h, matrix);
  1868. }
  1869. void sw_transform_index1_over_argb8888(
  1870. void *dst, const void *src, const uint32_t *src_clut,
  1871. uint16_t dst_pitch, uint16_t src_pitch, uint16_t src_w, uint16_t src_h,
  1872. int16_t x, int16_t y, uint16_t w, uint16_t h,
  1873. const sw_matrix_t *matrix)
  1874. {
  1875. sw_transform_index124_over_argb8888(dst, src, src_clut, dst_pitch, src_pitch,
  1876. src_w, src_h, 1, x, y, w, h, matrix);
  1877. }