123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /*
- * Copyright (c) 2020 Actions Technology Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /*********************
- * INCLUDES
- *********************/
- #include <math.h>
- #include <os_common_api.h>
- #include <display/sw_math.h>
- #include "effects_inner.h"
- /*********************
- * DEFINES
- *********************/
- #ifndef CONFIG_UI_EFFECT_TRANSFORM_BUFFER_COUNT
- # define CONFIG_UI_EFFECT_TRANSFORM_BUFFER_COUNT 2
- #endif
- #if CONFIG_UI_EFFECT_TRANSFORM_BUFFER_COUNT > 1
- # define DEF_MAX_FRAMES 16 /* near 267 ms for 60 Hz display */
- #else
- # define DEF_MAX_FRAMES 8 /* the frame-rate will cut by almost half for only 1 trans buffer */
- #endif
- /* SWITCH_EFFECT_PAGE: (set 0.0f for orthogonal projection) */
- #define CAMERA_DISTANCE 512.0f
- /* SCROLL_EFFECT_FAN, range (0, 90] */
- #define FAN_ANGLE 60
- /**********************
- * TYPEDEFS
- **********************/
- /**********************
- * STATIC PROTOTYPES
- **********************/
- static void _switch_effect_msg_cb(struct app_msg *msg, int result, void *unused);
- static void _switch_effect_transform_handle(const ui_transform_param_t *param, int *trans_end);
- #ifdef CONFIG_VG_LITE
- static int _vglite_switch_effect_handle(const ui_transform_param_t *param);
- #endif /* CONFIG_VG_LITE */
- #ifdef CONFIG_DMA2D_HAL
- static int _dma2d_init(graphic_buffer_t *dst);
- static int _dma2d_switch_effect_handle(const ui_transform_param_t *param);
- static int _dma2d_switch_proc_alpha_effect(const ui_transform_param_t *param);
- static int _dma2d_switch_proc_scale_effect(const ui_transform_param_t *param);
- #endif
- /**********************
- * STATIC VARIABLES
- **********************/
- static switch_effect_ctx_t switch_ctx = {
- .type = UI_SWITCH_EFFECT_NONE,
- .frame = 1,
- .max_frames = DEF_MAX_FRAMES,
- .trans_end = 1,
- #ifdef CONFIG_VG_LITE
- .opt_round_screen_overlapped = false,
- .camera_distance = CAMERA_DISTANCE,
- .fan = {
- .angle = FAN_ANGLE,
- },
- #endif
- };
- /**********************
- * GLOBAL FUNCTIONS
- **********************/
- int ui_switch_effect_set_type(uint8_t type)
- {
- if (type >= NUM_UI_SWITCH_EFFECTS)
- return -EINVAL;
- return ui_message_send_async2(VIEW_INVALID_ID, MSG_VIEW_USER_OFFSET, type, _switch_effect_msg_cb);
- }
- void ui_switch_effect_set_total_frames(uint16_t frame)
- {
- if (frame > 0)
- switch_ctx.max_frames = (int16_t)frame;
- }
- int32_t switch_effects_path_cos(int32_t start, int32_t end)
- {
- /* FIXME: both start & end less than (1 << 16)? */
- const int cos_shift = 16;
- const int32_t cos_max = sw_cos30(0) >> cos_shift;
- uint32_t angle = ui_map(switch_ctx.frame, 1, switch_ctx.max_frames, 900, 0);
- return ui_map(sw_cos30(angle) >> cos_shift, 0, cos_max, start, end);
- }
- /**********************
- * STATIC FUNCTIONS
- **********************/
- static void _switch_effect_change_type(void)
- {
- if (switch_ctx.type == switch_ctx.new_type)
- return;
- switch_ctx.type = switch_ctx.new_type;
- if (switch_ctx.type != UI_SWITCH_EFFECT_NONE) {
- view_manager_set_callback(UI_CB_TRANSFORM_SWITCH, _switch_effect_transform_handle);
- } else {
- view_manager_set_callback(UI_CB_TRANSFORM_SWITCH, NULL);
- }
- }
- static void _switch_effect_msg_cb(struct app_msg *msg, int result, void *unused)
- {
- switch_ctx.new_type = msg->value;
- if (switch_ctx.trans_end)
- _switch_effect_change_type();
- }
- static void _switch_effect_transform_handle(const ui_transform_param_t *param, int *trans_end)
- {
- int ret = -1;
- if (param->first_frame) {
- switch_ctx.frame = 1;
- switch_ctx.trans_end = 0;
- }
- if (switch_ctx.trans_end || *trans_end != 0)
- goto end_exit;
- os_strace_u32x2(SYS_TRACE_ID_VIEW_SWITCH_EFFECT, switch_ctx.type, switch_ctx.frame);
- #ifdef CONFIG_VG_LITE
- ret = _vglite_switch_effect_handle(param);
- #endif
- #ifdef CONFIG_DMA2D_HAL
- if (ret < 0) /* fallback to DMA2D */
- ret = _dma2d_switch_effect_handle(param);
- #endif
- os_strace_end_call(SYS_TRACE_ID_VIEW_SWITCH_EFFECT);
- if (!ret) {
- if (++switch_ctx.frame > switch_ctx.max_frames)
- switch_ctx.trans_end = 1;
- return;
- }
- end_exit:
- *trans_end = 1;
- switch_ctx.trans_end = 1;
- _switch_effect_change_type();
- }
- #ifdef CONFIG_VG_LITE
- static int _vglite_switch_effect_handle(const ui_transform_param_t *param)
- {
- switch (switch_ctx.type) {
- case UI_SWITCH_EFFECT_FAN:
- return vglite_switch_proc_fan_effect(&switch_ctx, param);
- case UI_SWITCH_EFFECT_PAGE:
- return vglite_switch_proc_page_effect(&switch_ctx, param);
- case UI_SWITCH_EFFECT_SCALE:
- return vglite_switch_proc_scale_effect(&switch_ctx, param);
- default:
- return -ENOSYS;
- }
- }
- #endif /* CONFIG_VG_LITE */
- #ifdef CONFIG_DMA2D_HAL
- static int _dma2d_switch_effect_handle(const ui_transform_param_t *param)
- {
- if (_dma2d_init(param->dst))
- return -ENODEV;
- switch (switch_ctx.type) {
- case UI_SWITCH_EFFECT_ALPHA:
- return _dma2d_switch_proc_alpha_effect(param);
- case UI_SWITCH_EFFECT_SCALE:
- return _dma2d_switch_proc_scale_effect(param);
- default:
- return -ENOSYS;
- }
- }
- static int _dma2d_init(graphic_buffer_t *dst)
- {
- hal_dma2d_handle_t *hdma2d = &switch_ctx.dma2d;
- uint16_t dst_pitch = dst->stride * dst->bits_per_pixel / 8;
- if (switch_ctx.dma2d_inited)
- return 0;
- if (hal_dma2d_init(hdma2d, HAL_DMA2D_FULL_MODES)) {
- SYS_LOG_ERR("transxxx failed to init dma2d %d\n");
- return -ENODEV;
- }
- switch_ctx.dma2d_inited = true;
- /* background layer */
- hdma2d->layer_cfg[0].input_pitch = dst_pitch;
- hdma2d->layer_cfg[0].input_width = dst->width;
- hdma2d->layer_cfg[0].input_height = dst->height;
- hdma2d->layer_cfg[0].color_format = dst->pixel_format;
- hdma2d->layer_cfg[0].alpha_mode = HAL_DMA2D_NO_MODIF_ALPHA;
- hdma2d->layer_cfg[0].input_alpha = 0xFF000000;
- hal_dma2d_config_layer(hdma2d, 0);
- /* foreground layer */
- hdma2d->layer_cfg[1].input_pitch = dst_pitch;
- hdma2d->layer_cfg[1].input_width = dst->width;
- hdma2d->layer_cfg[1].input_height = dst->height;
- hdma2d->layer_cfg[1].color_format = dst->pixel_format;
- hdma2d->layer_cfg[1].alpha_mode = HAL_DMA2D_COMBINE_ALPHA;
- hdma2d->layer_cfg[1].input_alpha = 0xFF000000;
- hal_dma2d_config_layer(hdma2d, 1);
- hdma2d->output_cfg.mode = HAL_DMA2D_M2M_BLEND;
- hdma2d->output_cfg.output_pitch = dst_pitch;
- hdma2d->output_cfg.color_format = dst->pixel_format;
- hal_dma2d_config_output(hdma2d);
- return 0;
- }
- static int _dma2d_switch_proc_alpha_effect(const ui_transform_param_t *param)
- {
- hal_dma2d_handle_t *hdma2d = &switch_ctx.dma2d;
- uint32_t old_alpha = 255 * (switch_ctx.max_frames - switch_ctx.frame) / switch_ctx.max_frames;
- hdma2d->output_cfg.mode = HAL_DMA2D_M2M_BLEND;
- hal_dma2d_config_output(hdma2d);
- hdma2d->layer_cfg[1].input_alpha = (old_alpha << 24);
- hal_dma2d_config_layer(hdma2d, 1);
- hal_dma2d_blending_start(hdma2d, (uint32_t)param->src_old->data, (uint32_t)param->src_new->data,
- (uint32_t)param->dst->data, param->dst->width, param->dst->height);
- hal_dma2d_poll_transfer(hdma2d, -1);
- return 0;
- }
- static int _dma2d_switch_proc_scale_effect(const ui_transform_param_t *param)
- {
- hal_dma2d_handle_t *hdma2d = &switch_ctx.dma2d;
- int16_t mid_frame = switch_ctx.max_frames / 2;
- int16_t scale_frame;
- int16_t scale_xres;
- int16_t scale_yres;
- uint32_t src_addr;
- bool zoom_out;
- /* fill black color */
- hdma2d->output_cfg.mode = HAL_DMA2D_R2M;
- hal_dma2d_config_output(hdma2d);
- hal_dma2d_start(hdma2d, 0, (uint32_t)param->dst->data, param->dst->width, param->dst->height);
- /* copy */
- hdma2d->output_cfg.mode = HAL_DMA2D_M2M;
- hal_dma2d_config_output(hdma2d);
- zoom_out = (switch_ctx.frame < mid_frame);
- if (zoom_out) {
- src_addr = (uint32_t)param->src_old->data;
- scale_frame = (mid_frame - switch_ctx.frame);
- } else {
- src_addr = (uint32_t)param->src_new->data;
- scale_frame = (switch_ctx.frame - mid_frame);
- }
- if (scale_frame > mid_frame)
- scale_frame = mid_frame;
- if (scale_frame > 0) {
- scale_xres = param->dst->width * scale_frame / mid_frame;
- scale_yres = param->dst->height * scale_frame / mid_frame;
- uint32_t dst_addr = (uint32_t)param->dst->data +
- (param->dst->stride * ((param->dst->height - scale_yres) / 2) +
- ((param->dst->width - scale_xres) / 2)) * param->dst->bits_per_pixel / 8;
- hal_dma2d_start(hdma2d, (uint32_t)src_addr, dst_addr, scale_xres, scale_yres);
- }
- hal_dma2d_poll_transfer(hdma2d, -1);
- return 0;
- }
- #endif /* CONFIG_DMA2D_HAL */
|