switch_effect.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (c) 2020 Actions Technology Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*********************
  7. * INCLUDES
  8. *********************/
  9. #include <math.h>
  10. #include <os_common_api.h>
  11. #include <display/sw_math.h>
  12. #include "effects_inner.h"
  13. /*********************
  14. * DEFINES
  15. *********************/
  16. #ifndef CONFIG_UI_EFFECT_TRANSFORM_BUFFER_COUNT
  17. # define CONFIG_UI_EFFECT_TRANSFORM_BUFFER_COUNT 2
  18. #endif
  19. #if CONFIG_UI_EFFECT_TRANSFORM_BUFFER_COUNT > 1
  20. # define DEF_MAX_FRAMES 16 /* near 267 ms for 60 Hz display */
  21. #else
  22. # define DEF_MAX_FRAMES 8 /* the frame-rate will cut by almost half for only 1 trans buffer */
  23. #endif
  24. /* SWITCH_EFFECT_PAGE: (set 0.0f for orthogonal projection) */
  25. #define CAMERA_DISTANCE 512.0f
  26. /* SCROLL_EFFECT_FAN, range (0, 90] */
  27. #define FAN_ANGLE 60
  28. /**********************
  29. * TYPEDEFS
  30. **********************/
  31. /**********************
  32. * STATIC PROTOTYPES
  33. **********************/
  34. static void _switch_effect_msg_cb(struct app_msg *msg, int result, void *unused);
  35. static void _switch_effect_transform_handle(const ui_transform_param_t *param, int *trans_end);
  36. #ifdef CONFIG_VG_LITE
  37. static int _vglite_switch_effect_handle(const ui_transform_param_t *param);
  38. #endif /* CONFIG_VG_LITE */
  39. #ifdef CONFIG_DMA2D_HAL
  40. static int _dma2d_init(graphic_buffer_t *dst);
  41. static int _dma2d_switch_effect_handle(const ui_transform_param_t *param);
  42. static int _dma2d_switch_proc_alpha_effect(const ui_transform_param_t *param);
  43. static int _dma2d_switch_proc_scale_effect(const ui_transform_param_t *param);
  44. #endif
  45. /**********************
  46. * STATIC VARIABLES
  47. **********************/
  48. static switch_effect_ctx_t switch_ctx = {
  49. .type = UI_SWITCH_EFFECT_NONE,
  50. .frame = 1,
  51. .max_frames = DEF_MAX_FRAMES,
  52. .trans_end = 1,
  53. #ifdef CONFIG_VG_LITE
  54. .opt_round_screen_overlapped = false,
  55. .camera_distance = CAMERA_DISTANCE,
  56. .fan = {
  57. .angle = FAN_ANGLE,
  58. },
  59. #endif
  60. };
  61. /**********************
  62. * GLOBAL FUNCTIONS
  63. **********************/
  64. int ui_switch_effect_set_type(uint8_t type)
  65. {
  66. if (type >= NUM_UI_SWITCH_EFFECTS)
  67. return -EINVAL;
  68. return ui_message_send_async2(VIEW_INVALID_ID, MSG_VIEW_USER_OFFSET, type, _switch_effect_msg_cb);
  69. }
  70. void ui_switch_effect_set_total_frames(uint16_t frame)
  71. {
  72. if (frame > 0)
  73. switch_ctx.max_frames = (int16_t)frame;
  74. }
  75. int32_t switch_effects_path_cos(int32_t start, int32_t end)
  76. {
  77. /* FIXME: both start & end less than (1 << 16)? */
  78. const int cos_shift = 16;
  79. const int32_t cos_max = sw_cos30(0) >> cos_shift;
  80. uint32_t angle = ui_map(switch_ctx.frame, 1, switch_ctx.max_frames, 900, 0);
  81. return ui_map(sw_cos30(angle) >> cos_shift, 0, cos_max, start, end);
  82. }
  83. /**********************
  84. * STATIC FUNCTIONS
  85. **********************/
  86. static void _switch_effect_change_type(void)
  87. {
  88. if (switch_ctx.type == switch_ctx.new_type)
  89. return;
  90. switch_ctx.type = switch_ctx.new_type;
  91. if (switch_ctx.type != UI_SWITCH_EFFECT_NONE) {
  92. view_manager_set_callback(UI_CB_TRANSFORM_SWITCH, _switch_effect_transform_handle);
  93. } else {
  94. view_manager_set_callback(UI_CB_TRANSFORM_SWITCH, NULL);
  95. }
  96. }
  97. static void _switch_effect_msg_cb(struct app_msg *msg, int result, void *unused)
  98. {
  99. switch_ctx.new_type = msg->value;
  100. if (switch_ctx.trans_end)
  101. _switch_effect_change_type();
  102. }
  103. static void _switch_effect_transform_handle(const ui_transform_param_t *param, int *trans_end)
  104. {
  105. int ret = -1;
  106. if (param->first_frame) {
  107. switch_ctx.frame = 1;
  108. switch_ctx.trans_end = 0;
  109. }
  110. if (switch_ctx.trans_end || *trans_end != 0)
  111. goto end_exit;
  112. os_strace_u32x2(SYS_TRACE_ID_VIEW_SWITCH_EFFECT, switch_ctx.type, switch_ctx.frame);
  113. #ifdef CONFIG_VG_LITE
  114. ret = _vglite_switch_effect_handle(param);
  115. #endif
  116. #ifdef CONFIG_DMA2D_HAL
  117. if (ret < 0) /* fallback to DMA2D */
  118. ret = _dma2d_switch_effect_handle(param);
  119. #endif
  120. os_strace_end_call(SYS_TRACE_ID_VIEW_SWITCH_EFFECT);
  121. if (!ret) {
  122. if (++switch_ctx.frame > switch_ctx.max_frames)
  123. switch_ctx.trans_end = 1;
  124. return;
  125. }
  126. end_exit:
  127. *trans_end = 1;
  128. switch_ctx.trans_end = 1;
  129. _switch_effect_change_type();
  130. }
  131. #ifdef CONFIG_VG_LITE
  132. static int _vglite_switch_effect_handle(const ui_transform_param_t *param)
  133. {
  134. switch (switch_ctx.type) {
  135. case UI_SWITCH_EFFECT_FAN:
  136. return vglite_switch_proc_fan_effect(&switch_ctx, param);
  137. case UI_SWITCH_EFFECT_PAGE:
  138. return vglite_switch_proc_page_effect(&switch_ctx, param);
  139. case UI_SWITCH_EFFECT_SCALE:
  140. return vglite_switch_proc_scale_effect(&switch_ctx, param);
  141. default:
  142. return -ENOSYS;
  143. }
  144. }
  145. #endif /* CONFIG_VG_LITE */
  146. #ifdef CONFIG_DMA2D_HAL
  147. static int _dma2d_switch_effect_handle(const ui_transform_param_t *param)
  148. {
  149. if (_dma2d_init(param->dst))
  150. return -ENODEV;
  151. switch (switch_ctx.type) {
  152. case UI_SWITCH_EFFECT_ALPHA:
  153. return _dma2d_switch_proc_alpha_effect(param);
  154. case UI_SWITCH_EFFECT_SCALE:
  155. return _dma2d_switch_proc_scale_effect(param);
  156. default:
  157. return -ENOSYS;
  158. }
  159. }
  160. static int _dma2d_init(graphic_buffer_t *dst)
  161. {
  162. hal_dma2d_handle_t *hdma2d = &switch_ctx.dma2d;
  163. uint16_t dst_pitch = dst->stride * dst->bits_per_pixel / 8;
  164. if (switch_ctx.dma2d_inited)
  165. return 0;
  166. if (hal_dma2d_init(hdma2d, HAL_DMA2D_FULL_MODES)) {
  167. SYS_LOG_ERR("transxxx failed to init dma2d %d\n");
  168. return -ENODEV;
  169. }
  170. switch_ctx.dma2d_inited = true;
  171. /* background layer */
  172. hdma2d->layer_cfg[0].input_pitch = dst_pitch;
  173. hdma2d->layer_cfg[0].input_width = dst->width;
  174. hdma2d->layer_cfg[0].input_height = dst->height;
  175. hdma2d->layer_cfg[0].color_format = dst->pixel_format;
  176. hdma2d->layer_cfg[0].alpha_mode = HAL_DMA2D_NO_MODIF_ALPHA;
  177. hdma2d->layer_cfg[0].input_alpha = 0xFF000000;
  178. hal_dma2d_config_layer(hdma2d, 0);
  179. /* foreground layer */
  180. hdma2d->layer_cfg[1].input_pitch = dst_pitch;
  181. hdma2d->layer_cfg[1].input_width = dst->width;
  182. hdma2d->layer_cfg[1].input_height = dst->height;
  183. hdma2d->layer_cfg[1].color_format = dst->pixel_format;
  184. hdma2d->layer_cfg[1].alpha_mode = HAL_DMA2D_COMBINE_ALPHA;
  185. hdma2d->layer_cfg[1].input_alpha = 0xFF000000;
  186. hal_dma2d_config_layer(hdma2d, 1);
  187. hdma2d->output_cfg.mode = HAL_DMA2D_M2M_BLEND;
  188. hdma2d->output_cfg.output_pitch = dst_pitch;
  189. hdma2d->output_cfg.color_format = dst->pixel_format;
  190. hal_dma2d_config_output(hdma2d);
  191. return 0;
  192. }
  193. static int _dma2d_switch_proc_alpha_effect(const ui_transform_param_t *param)
  194. {
  195. hal_dma2d_handle_t *hdma2d = &switch_ctx.dma2d;
  196. uint32_t old_alpha = 255 * (switch_ctx.max_frames - switch_ctx.frame) / switch_ctx.max_frames;
  197. hdma2d->output_cfg.mode = HAL_DMA2D_M2M_BLEND;
  198. hal_dma2d_config_output(hdma2d);
  199. hdma2d->layer_cfg[1].input_alpha = (old_alpha << 24);
  200. hal_dma2d_config_layer(hdma2d, 1);
  201. hal_dma2d_blending_start(hdma2d, (uint32_t)param->src_old->data, (uint32_t)param->src_new->data,
  202. (uint32_t)param->dst->data, param->dst->width, param->dst->height);
  203. hal_dma2d_poll_transfer(hdma2d, -1);
  204. return 0;
  205. }
  206. static int _dma2d_switch_proc_scale_effect(const ui_transform_param_t *param)
  207. {
  208. hal_dma2d_handle_t *hdma2d = &switch_ctx.dma2d;
  209. int16_t mid_frame = switch_ctx.max_frames / 2;
  210. int16_t scale_frame;
  211. int16_t scale_xres;
  212. int16_t scale_yres;
  213. uint32_t src_addr;
  214. bool zoom_out;
  215. /* fill black color */
  216. hdma2d->output_cfg.mode = HAL_DMA2D_R2M;
  217. hal_dma2d_config_output(hdma2d);
  218. hal_dma2d_start(hdma2d, 0, (uint32_t)param->dst->data, param->dst->width, param->dst->height);
  219. /* copy */
  220. hdma2d->output_cfg.mode = HAL_DMA2D_M2M;
  221. hal_dma2d_config_output(hdma2d);
  222. zoom_out = (switch_ctx.frame < mid_frame);
  223. if (zoom_out) {
  224. src_addr = (uint32_t)param->src_old->data;
  225. scale_frame = (mid_frame - switch_ctx.frame);
  226. } else {
  227. src_addr = (uint32_t)param->src_new->data;
  228. scale_frame = (switch_ctx.frame - mid_frame);
  229. }
  230. if (scale_frame > mid_frame)
  231. scale_frame = mid_frame;
  232. if (scale_frame > 0) {
  233. scale_xres = param->dst->width * scale_frame / mid_frame;
  234. scale_yres = param->dst->height * scale_frame / mid_frame;
  235. uint32_t dst_addr = (uint32_t)param->dst->data +
  236. (param->dst->stride * ((param->dst->height - scale_yres) / 2) +
  237. ((param->dst->width - scale_xres) / 2)) * param->dst->bits_per_pixel / 8;
  238. hal_dma2d_start(hdma2d, (uint32_t)src_addr, dst_addr, scale_xres, scale_yres);
  239. }
  240. hal_dma2d_poll_transfer(hdma2d, -1);
  241. return 0;
  242. }
  243. #endif /* CONFIG_DMA2D_HAL */