view_cache_lite.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file view cache interface
  8. */
  9. #ifndef CONFIG_VIEW_SCROLL_MEM_DEFAULT
  10. #define LOG_MODULE_CUSTOMER
  11. #include <os_common_api.h>
  12. #include <ui_manager.h>
  13. #include <view_cache.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. LOG_MODULE_REGISTER(view_cache, LOG_LEVEL_INF);
  17. #define MAX_VIEW_CACHE (sizeof(uint32_t) * 8)
  18. typedef struct {
  19. const view_cache_dsc_t *dsc;
  20. uint32_t stat;
  21. uint8_t rotate : 1;
  22. int8_t main_idx; /* focused main idx in vlist */
  23. int8_t focus_idx; /* focused idx also considering cross_vlist */
  24. int8_t load_idx; /* the index that is loading */
  25. /* save the initial param */
  26. int8_t init_main_idx;
  27. int8_t init_focus_idx;
  28. } view_cache_ctx_t;
  29. static int view_cache_view_transforming = 0;
  30. static int view_cache_serial_load_paused = 0;
  31. static int _view_cache_set_focus(uint16_t view_id);
  32. static int _view_cache_set_focus_idx(int8_t main_idx, bool in_restore);
  33. static view_cache_ctx_t view_cache_ctx;
  34. static view_cache_focus_cb_t last_focus_cb;
  35. static uint16_t last_focus_view;
  36. static OS_MUTEX_DEFINE(view_cache_mutex);
  37. static uint16_t _view_cache_get_view_id(uint8_t idx)
  38. {
  39. if (idx < view_cache_ctx.dsc->num) {
  40. return view_cache_ctx.dsc->vlist[idx];
  41. } else if (idx < view_cache_ctx.dsc->num + 2) {
  42. return view_cache_ctx.dsc->cross_vlist[idx - view_cache_ctx.dsc->num];
  43. } else {
  44. return VIEW_INVALID_ID;
  45. }
  46. }
  47. static const void * _view_cache_get_presenter(uint8_t idx)
  48. {
  49. if (idx < view_cache_ctx.dsc->num) {
  50. return view_cache_ctx.dsc->plist ? view_cache_ctx.dsc->plist[idx] : NULL;
  51. } else if (idx < view_cache_ctx.dsc->num + 2) {
  52. return view_cache_ctx.dsc->cross_plist[idx - view_cache_ctx.dsc->num];
  53. } else {
  54. return NULL;
  55. }
  56. }
  57. static uint8_t _view_cache_get_create_flags(uint8_t idx)
  58. {
  59. if (idx < view_cache_ctx.dsc->num && view_cache_ctx.dsc->vlist_create_flags) {
  60. return view_cache_ctx.dsc->vlist_create_flags[idx];
  61. } else {
  62. return 0;
  63. }
  64. }
  65. static int8_t _view_cache_get_main_idx(uint16_t view_id)
  66. {
  67. int8_t idx;
  68. for (idx = view_cache_ctx.dsc->num - 1; idx >= 0; idx--) {
  69. if (view_cache_ctx.dsc->vlist[idx] == view_id) {
  70. return idx;
  71. }
  72. }
  73. return -1;
  74. }
  75. static int8_t _view_cache_get_idx(uint16_t view_id)
  76. {
  77. if (view_id == view_cache_ctx.dsc->cross_vlist[0]) {
  78. return view_cache_ctx.dsc->num;
  79. } else if (view_id == view_cache_ctx.dsc->cross_vlist[1]) {
  80. return view_cache_ctx.dsc->num + 1;
  81. } else {
  82. return _view_cache_get_main_idx(view_id);
  83. }
  84. }
  85. static int _view_cache_load(uint8_t idx, uint8_t create_flags)
  86. {
  87. uint16_t view_id;
  88. if (view_cache_ctx.stat & (1 << idx))
  89. return -EALREADY;
  90. view_id = _view_cache_get_view_id(idx);
  91. if (view_id != VIEW_INVALID_ID) {
  92. view_cache_ctx.stat |= (1 << idx);
  93. create_flags |= _view_cache_get_create_flags(idx);
  94. return ui_view_create(view_id, _view_cache_get_presenter(idx), create_flags);
  95. }
  96. return -EINVAL;
  97. }
  98. static void _view_cache_unload(uint8_t idx)
  99. {
  100. uint16_t view_id;
  101. if (!(view_cache_ctx.stat & (1 << idx)))
  102. return;
  103. view_id = _view_cache_get_view_id(idx);
  104. assert(view_id != VIEW_INVALID_ID);
  105. view_cache_ctx.stat &= ~(1 << idx);
  106. ui_view_delete(view_id);
  107. }
  108. static int _view_cache_set_attr(uint8_t idx, uint8_t attr, bool keep_pos, bool by_msg)
  109. {
  110. uint16_t view_id;
  111. if (!(view_cache_ctx.stat & (1 << idx)))
  112. return -EINVAL;
  113. view_id = _view_cache_get_view_id(idx);
  114. assert(view_id != VIEW_INVALID_ID);
  115. if (by_msg) {
  116. return ui_view_set_drag_attribute(view_id, attr, keep_pos);
  117. } else {
  118. return view_set_drag_attribute(view_id, attr, keep_pos);
  119. }
  120. }
  121. static int8_t _view_cache_rotate_main_idx(int8_t idx)
  122. {
  123. while (idx < 0)
  124. idx += view_cache_ctx.dsc->num;
  125. while (idx >= view_cache_ctx.dsc->num)
  126. idx -= view_cache_ctx.dsc->num;
  127. return idx;
  128. }
  129. static bool _view_cache_main_idx_is_in_range(int8_t idx)
  130. {
  131. int8_t min_idx = view_cache_ctx.main_idx - 1;
  132. int8_t max_idx = view_cache_ctx.main_idx + 1;
  133. if (view_cache_ctx.rotate) {
  134. if (view_cache_ctx.dsc->num <= (1 * 2 + 1))
  135. return true;
  136. idx = _view_cache_rotate_main_idx(idx);
  137. if (min_idx < 0) {
  138. min_idx += view_cache_ctx.dsc->num;
  139. if (idx >= min_idx || idx <= max_idx)
  140. return true;
  141. } else if (max_idx >= view_cache_ctx.dsc->num) {
  142. max_idx -= view_cache_ctx.dsc->num;
  143. if (idx >= min_idx || idx <= max_idx)
  144. return true;
  145. } else if (idx >= min_idx && idx <= max_idx) {
  146. return true;
  147. }
  148. } else {
  149. if (idx >= UI_MAX(min_idx, 0) &&
  150. idx <= UI_MIN(max_idx, view_cache_ctx.dsc->num - 1))
  151. return true;
  152. }
  153. return false;
  154. }
  155. static int _view_cache_load_main(int8_t idx, uint8_t create_flags)
  156. {
  157. if (view_cache_ctx.rotate) {
  158. idx = _view_cache_rotate_main_idx(idx);
  159. } else if (idx < 0 || idx >= view_cache_ctx.dsc->num) {
  160. return -EINVAL;
  161. }
  162. return _view_cache_load(idx, create_flags);
  163. }
  164. static void _view_cache_unload_main(int8_t idx, bool forced)
  165. {
  166. if (view_cache_ctx.rotate) {
  167. if (!forced && _view_cache_main_idx_is_in_range(idx))
  168. return;
  169. idx = _view_cache_rotate_main_idx(idx);
  170. } else if (idx < 0 || idx >= view_cache_ctx.dsc->num) {
  171. return;
  172. }
  173. _view_cache_unload(idx);
  174. }
  175. static int _view_cache_set_attr_main(int8_t idx, uint8_t attr, bool by_msg)
  176. {
  177. if (view_cache_ctx.rotate) {
  178. idx = _view_cache_rotate_main_idx(idx);
  179. } else if (idx < 0 || idx >= view_cache_ctx.dsc->num) {
  180. return -EINVAL;
  181. }
  182. return _view_cache_set_attr(idx, attr, false, by_msg);
  183. }
  184. static uint8_t _view_cache_rotate_drag_attr(uint8_t drag_attr)
  185. {
  186. static const uint8_t s_attr_rotated[][4] = {
  187. { UI_DRAG_DROPLEFT, UI_DRAG_DROPRIGHT, UI_DRAG_DROPUP, UI_DRAG_DROPDOWN },
  188. { UI_DRAG_DROPUP, UI_DRAG_DROPDOWN, UI_DRAG_DROPRIGHT, UI_DRAG_DROPLEFT },
  189. { UI_DRAG_DROPRIGHT, UI_DRAG_DROPLEFT, UI_DRAG_DROPDOWN, UI_DRAG_DROPUP },
  190. };
  191. uint16_t rotation = view_manager_get_disp_rotation();
  192. const uint8_t *rotated_attr;
  193. uint8_t new_attr = 0;
  194. if (drag_attr == 0 || rotation == 0)
  195. return drag_attr;
  196. if (rotation == 90) {
  197. rotated_attr = s_attr_rotated[0];
  198. } else if (rotation == 180) {
  199. rotated_attr = s_attr_rotated[1];
  200. } else {
  201. rotated_attr = s_attr_rotated[2];
  202. }
  203. if (drag_attr & 0x0f) {
  204. for (int i = 0; i < 4; i++) {
  205. if (drag_attr & (1 << i)) {
  206. new_attr |= rotated_attr[i];
  207. }
  208. }
  209. }
  210. if (drag_attr & 0xf0) {
  211. for (int i = 4; i < 8; i++) {
  212. if (drag_attr & (1 << i)) {
  213. new_attr |= rotated_attr[i - 4] << 4;
  214. }
  215. }
  216. }
  217. return new_attr;
  218. }
  219. static uint8_t _view_cache_decide_attr_main(int8_t idx)
  220. {
  221. int8_t left_idx = view_cache_ctx.main_idx - 1;
  222. int8_t right_idx = view_cache_ctx.main_idx + 1;
  223. uint8_t attr = 0;
  224. if (view_cache_ctx.rotate) {
  225. idx = _view_cache_rotate_main_idx(idx);
  226. left_idx = _view_cache_rotate_main_idx(left_idx);
  227. right_idx = _view_cache_rotate_main_idx(right_idx);
  228. }
  229. if (view_cache_ctx.dsc->type == LANDSCAPE) {
  230. if (view_cache_ctx.rotate && view_cache_ctx.dsc->num == 2) {
  231. attr = (idx == view_cache_ctx.main_idx) ? 0 :
  232. (UI_DRAG_MOVERIGHT | UI_DRAG_MOVELEFT);
  233. }
  234. if (idx == left_idx)
  235. attr = UI_DRAG_MOVERIGHT;
  236. else if (idx == right_idx)
  237. attr = UI_DRAG_MOVELEFT;
  238. } else {
  239. if (view_cache_ctx.rotate && view_cache_ctx.dsc->num == 2) {
  240. attr = (idx == view_cache_ctx.main_idx) ? 0 :
  241. (UI_DRAG_MOVEDOWN | UI_DRAG_MOVEUP);
  242. }
  243. if (idx == left_idx)
  244. attr = UI_DRAG_MOVEDOWN;
  245. else if (idx == right_idx)
  246. attr = UI_DRAG_MOVEUP;
  247. }
  248. return _view_cache_rotate_drag_attr(attr);
  249. }
  250. static uint8_t _view_cache_decide_attr_cross(int8_t idx)
  251. {
  252. uint8_t attr = 0;
  253. if (view_cache_ctx.dsc->type == LANDSCAPE) {
  254. if (idx == view_cache_ctx.dsc->num)
  255. attr = UI_DRAG_DROPDOWN;
  256. else if (idx == view_cache_ctx.dsc->num + 1)
  257. attr = UI_DRAG_DROPUP;
  258. } else {
  259. if (idx == view_cache_ctx.dsc->num)
  260. attr = UI_DRAG_DROPRIGHT;
  261. else if (idx == view_cache_ctx.dsc->num + 1)
  262. attr = UI_DRAG_DROPLEFT;
  263. }
  264. return _view_cache_rotate_drag_attr(attr);
  265. }
  266. static void _view_cache_serial_load(void)
  267. {
  268. int8_t main_idx = view_cache_ctx.main_idx;
  269. int8_t load_idx;
  270. /* load the "cross_attached_view" main view as soon as possible */
  271. if (!_view_cache_load(main_idx, UI_CREATE_FLAG_SHOW)) {
  272. return;
  273. }
  274. /* load cross views */
  275. for(; view_cache_ctx.load_idx >= view_cache_ctx.dsc->num; view_cache_ctx.load_idx--) {
  276. if (!_view_cache_load(view_cache_ctx.load_idx, UI_CREATE_FLAG_NO_FB)) {
  277. return;
  278. }
  279. }
  280. /* load right main view */
  281. if (view_cache_ctx.rotate) {
  282. load_idx = _view_cache_rotate_main_idx(main_idx + 1);
  283. } else {
  284. load_idx = main_idx + 1;
  285. }
  286. if (_view_cache_main_idx_is_in_range(load_idx) &&
  287. !_view_cache_load(load_idx, 0)) {
  288. return;
  289. }
  290. /* load left main view */
  291. if (view_cache_ctx.init_focus_idx == main_idx) {
  292. if (view_cache_ctx.rotate) {
  293. load_idx = _view_cache_rotate_main_idx(main_idx - 1);
  294. } else {
  295. load_idx = main_idx - 1;
  296. }
  297. if (_view_cache_main_idx_is_in_range(load_idx) &&
  298. !_view_cache_load(load_idx, 0)) {
  299. return;
  300. }
  301. }
  302. /* load end */
  303. view_cache_ctx.load_idx = -1;
  304. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  305. ui_manager_set_max_buffer_count(CONFIG_SURFACE_MAX_BUFFER_COUNT);
  306. #endif
  307. /* set cross view attribute */
  308. if (view_cache_ctx.dsc->cross_attached_view == VIEW_INVALID_ID ||
  309. view_cache_ctx.dsc->cross_attached_view == view_cache_ctx.dsc->vlist[main_idx]) {
  310. if (view_cache_ctx.dsc->num != view_cache_ctx.init_focus_idx) {
  311. _view_cache_set_attr(view_cache_ctx.dsc->num,
  312. _view_cache_decide_attr_cross(view_cache_ctx.dsc->num), false, true);
  313. }
  314. if (view_cache_ctx.dsc->num + 1 != view_cache_ctx.init_focus_idx) {
  315. _view_cache_set_attr(view_cache_ctx.dsc->num + 1,
  316. _view_cache_decide_attr_cross(view_cache_ctx.dsc->num + 1), false, true);
  317. }
  318. }
  319. /* set right-left view attribute */
  320. _view_cache_set_attr_main(main_idx + 1, _view_cache_decide_attr_main(main_idx + 1), false);
  321. if (!view_cache_ctx.rotate || view_cache_ctx.dsc->num != 2)
  322. _view_cache_set_attr_main(main_idx - 1, _view_cache_decide_attr_main(main_idx - 1), false);
  323. }
  324. static void _view_cache_scroll_cb(uint16_t view_id, uint8_t msg_id)
  325. {
  326. const view_cache_dsc_t *dsc;
  327. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  328. dsc = view_cache_ctx.dsc;
  329. if (dsc == NULL) {
  330. goto out_unlock;
  331. }
  332. if (view_cache_ctx.load_idx >= 0) {
  333. goto out_unlock;
  334. }
  335. if (msg_id == MSG_VIEW_SCROLL_BEGIN) {
  336. if (view_id == dsc->cross_vlist[0] || view_id == dsc->cross_vlist[1]) {
  337. _view_cache_unload_main(view_cache_ctx.main_idx - 1, true);
  338. }
  339. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  340. ui_manager_set_max_buffer_count(1);
  341. #endif
  342. } else {
  343. if (view_id != VIEW_INVALID_ID &&
  344. view_id != dsc->cross_vlist[0] &&
  345. view_id != dsc->cross_vlist[1]) {
  346. _view_cache_set_focus(view_id);
  347. }
  348. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  349. ui_manager_set_max_buffer_count(CONFIG_SURFACE_MAX_BUFFER_COUNT);
  350. #endif
  351. }
  352. out_unlock:
  353. os_mutex_unlock(&view_cache_mutex);
  354. }
  355. static void _view_cache_monitor_cb(uint16_t view_id, uint8_t msg_id, void *msg_data)
  356. {
  357. int8_t idx;
  358. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  359. if (view_cache_ctx.dsc == NULL) {
  360. if (msg_id == MSG_VIEW_DEFOCUS && last_focus_cb && view_id == last_focus_view) {
  361. last_focus_cb(view_id, false);
  362. last_focus_cb = NULL;
  363. }
  364. goto out_unlock;
  365. }
  366. idx = _view_cache_get_idx(view_id);
  367. if (idx < 0) {
  368. goto out_unlock;
  369. }
  370. if (msg_id == MSG_VIEW_FOCUS || msg_id == MSG_VIEW_DEFOCUS) {
  371. bool focused = (msg_id == MSG_VIEW_FOCUS);
  372. if (focused) {
  373. view_cache_ctx.focus_idx = idx;
  374. }
  375. if (view_cache_ctx.dsc->focus_cb)
  376. view_cache_ctx.dsc->focus_cb(view_id, focused);
  377. } else if (msg_id == MSG_VIEW_SCROLL_BEGIN || msg_id == MSG_VIEW_SCROLL_END) {
  378. if (view_cache_ctx.dsc->monitor_cb)
  379. view_cache_ctx.dsc->monitor_cb(view_id, msg_id);
  380. } else if (msg_id == MSG_VIEW_LAYOUT) {
  381. if (view_cache_ctx.load_idx >= 0) {
  382. if (view_cache_view_transforming) {
  383. SYS_LOG_INF("view serial load paused after %d\n", view_id);
  384. view_cache_serial_load_paused = 1;
  385. } else {
  386. _view_cache_serial_load();
  387. }
  388. } else {
  389. int8_t idx = _view_cache_get_main_idx(view_id);
  390. if (idx >= 0) { /* in case that previous set_attr() failed */
  391. _view_cache_set_attr_main(idx, _view_cache_decide_attr_main(idx), false);
  392. }
  393. }
  394. } else if(msg_id == MSG_VIEW_TRANSFORM_START) {
  395. view_cache_view_transforming = 1;
  396. } else if (msg_id == MSG_VIEW_TRANSFORM_END) {
  397. SYS_LOG_INF("view serial load resume after %d\n", view_id);
  398. view_cache_view_transforming = 0;
  399. if (view_cache_serial_load_paused == 1) {
  400. view_cache_serial_load_paused = 0;
  401. _view_cache_serial_load();
  402. }
  403. }
  404. out_unlock:
  405. os_mutex_unlock(&view_cache_mutex);
  406. }
  407. int view_cache_init(const view_cache_dsc_t *dsc, uint16_t init_view)
  408. {
  409. return view_cache_init2(dsc, init_view, VIEW_INVALID_ID);
  410. }
  411. int view_cache_init2(const view_cache_dsc_t *dsc,
  412. uint16_t init_focus_view, uint16_t init_main_view)
  413. {
  414. int8_t init_main_idx = -1; /* index of init_main_view */
  415. int8_t main_idx = -1;
  416. int8_t cross_idx = -1;
  417. int8_t cross_attached_idx = -1;
  418. int8_t idx;
  419. int res = -EINVAL;
  420. /* Also consider the cross views */
  421. if (dsc == NULL || dsc->num <= 0 || dsc->num + 2 > MAX_VIEW_CACHE) {
  422. goto out_fail;
  423. }
  424. if (init_focus_view == VIEW_INVALID_ID) {
  425. goto out_fail;
  426. }
  427. for (idx = dsc->num - 1; idx >= 0; idx--) {
  428. if (dsc->vlist[idx] == VIEW_INVALID_ID)
  429. goto out_fail;
  430. if (dsc->vlist[idx] == init_focus_view)
  431. main_idx = idx;
  432. if (dsc->vlist[idx] == init_main_view)
  433. init_main_idx = idx;
  434. if (dsc->vlist[idx] == dsc->cross_attached_view)
  435. cross_attached_idx = idx;
  436. }
  437. if (main_idx < 0) {
  438. if (init_focus_view == dsc->cross_vlist[0]) {
  439. cross_idx = dsc->num;
  440. } else if (init_focus_view == dsc->cross_vlist[1]) {
  441. cross_idx = dsc->num + 1;
  442. } else {
  443. goto out_fail;
  444. }
  445. if (init_main_idx >= 0) {
  446. main_idx = init_main_idx;
  447. } else if (cross_attached_idx >= 0) {
  448. main_idx = cross_attached_idx;
  449. } else { /* FIXME: just select the middle view ? */
  450. main_idx = (dsc->num / 2);
  451. }
  452. }
  453. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  454. if (view_cache_ctx.dsc) {
  455. SYS_LOG_WRN("view_cache: already init");
  456. res = -EALREADY;
  457. goto out_unlock;
  458. }
  459. view_cache_ctx.dsc = dsc;
  460. view_cache_ctx.main_idx = -1;
  461. view_cache_ctx.focus_idx = -1;
  462. view_cache_ctx.rotate = (view_cache_ctx.dsc->rotate && view_cache_ctx.dsc->num >= 2);
  463. view_cache_ctx.init_main_idx = main_idx;
  464. view_cache_ctx.init_focus_idx = (cross_idx >= 0) ? cross_idx : main_idx;
  465. ui_manager_set_scroll_callback(_view_cache_scroll_cb);
  466. ui_manager_set_monitor_callback(_view_cache_monitor_cb);
  467. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  468. ui_manager_set_max_buffer_count(1);
  469. #endif
  470. view_cache_ctx.load_idx = dsc->num + 1;
  471. view_cache_ctx.main_idx = main_idx;
  472. /* load focused view */
  473. if (cross_idx < 0) {
  474. _view_cache_load(main_idx, UI_CREATE_FLAG_SHOW);
  475. } else if (!_view_cache_load(cross_idx, UI_CREATE_FLAG_SHOW)) {
  476. _view_cache_set_attr(cross_idx, _view_cache_decide_attr_cross(cross_idx), true, true);
  477. }
  478. res = 0;
  479. out_unlock:
  480. SYS_LOG_INF("view_cache: init %u, main %u (res=%d)", init_focus_view, init_main_view, res);
  481. os_mutex_unlock(&view_cache_mutex);
  482. return res;
  483. out_fail:
  484. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  485. goto out_unlock;
  486. }
  487. int view_cache_deinit(void)
  488. {
  489. int8_t idx;
  490. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  491. if (view_cache_ctx.dsc == NULL) {
  492. SYS_LOG_WRN("view_cache: not init yet");
  493. os_mutex_unlock(&view_cache_mutex);
  494. return EALREADY;
  495. }
  496. ui_manager_set_scroll_callback(NULL);
  497. if (view_cache_ctx.focus_idx >= 0 && view_cache_ctx.dsc->focus_cb) {
  498. last_focus_view = _view_cache_get_view_id(view_cache_ctx.focus_idx);
  499. last_focus_cb = view_cache_ctx.dsc->focus_cb;
  500. } else {
  501. last_focus_cb = NULL;
  502. }
  503. /* delete the main views first to avoid unexpected focus changes */
  504. for (idx = 0; idx < view_cache_ctx.dsc->num + 2; idx++) {
  505. _view_cache_unload(idx);
  506. }
  507. ui_manager_set_monitor_callback(NULL);
  508. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  509. ui_manager_set_max_buffer_count(CONFIG_SURFACE_MAX_BUFFER_COUNT);
  510. #endif
  511. memset(&view_cache_ctx, 0, sizeof(view_cache_ctx));
  512. if (is_in_ui_thread() && last_focus_cb) { /* notify the defocus */
  513. last_focus_cb(last_focus_view, false);
  514. last_focus_cb = NULL;
  515. }
  516. SYS_LOG_INF("view_cache: deinit");
  517. view_cache_view_transforming = 0;
  518. view_cache_serial_load_paused = 0;
  519. os_mutex_unlock(&view_cache_mutex);
  520. return 0;
  521. }
  522. void view_cache_wait_last_focus_cb(void)
  523. {
  524. /* neither in uisrv nor executed yet */
  525. if (last_focus_cb) {
  526. ui_message_wait_reply();
  527. }
  528. }
  529. uint16_t view_cache_get_focus_view(void)
  530. {
  531. uint16_t view_id = VIEW_INVALID_ID;
  532. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  533. if (view_cache_ctx.dsc) {
  534. int8_t focus_idx = (view_cache_ctx.focus_idx >= 0) ?
  535. view_cache_ctx.focus_idx : view_cache_ctx.init_focus_idx;
  536. view_id = _view_cache_get_view_id(focus_idx);
  537. }
  538. os_mutex_unlock(&view_cache_mutex);
  539. return view_id;
  540. }
  541. uint16_t view_cache_get_focus_main_view(void)
  542. {
  543. uint16_t view_id = VIEW_INVALID_ID;
  544. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  545. if (view_cache_ctx.dsc) {
  546. int8_t main_idx = (view_cache_ctx.main_idx >= 0) ?
  547. view_cache_ctx.main_idx : view_cache_ctx.init_main_idx;
  548. view_id = _view_cache_get_view_id(main_idx);
  549. }
  550. os_mutex_unlock(&view_cache_mutex);
  551. return view_id;
  552. }
  553. int view_cache_set_focus_view(uint16_t view_id)
  554. {
  555. const view_cache_dsc_t *dsc;
  556. uint16_t main_view_Id;
  557. int8_t idx;
  558. SYS_LOG_INF("view_cache: set focus view %u", view_id);
  559. os_mutex_lock(&view_cache_mutex, OS_FOREVER);
  560. dsc = view_cache_ctx.dsc;
  561. if (dsc == NULL) {
  562. os_mutex_unlock(&view_cache_mutex);
  563. return -ESRCH;
  564. }
  565. idx = _view_cache_get_idx(view_id);
  566. if (idx < 0) {
  567. os_mutex_unlock(&view_cache_mutex);
  568. return -EINVAL;
  569. }
  570. int8_t focus_idx = (view_cache_ctx.focus_idx >= 0) ?
  571. view_cache_ctx.focus_idx : view_cache_ctx.init_focus_idx;
  572. if (idx == focus_idx) {
  573. os_mutex_unlock(&view_cache_mutex);
  574. return 0;
  575. }
  576. main_view_Id = _view_cache_get_view_id(view_cache_ctx.main_idx);
  577. os_mutex_unlock(&view_cache_mutex);
  578. view_cache_deinit();
  579. return view_cache_init2(dsc, view_id, main_view_Id);
  580. }
  581. int view_cache_shrink(void)
  582. {
  583. return 0;
  584. }
  585. void view_cache_dump(void)
  586. {
  587. uint8_t i;
  588. if (view_cache_ctx.dsc == NULL)
  589. return;
  590. os_printk("view cache:\n\t main(%u):", view_cache_ctx.dsc->num);
  591. for (i = 0; i < view_cache_ctx.dsc->num; i++) {
  592. os_printk(" %c%u", (i == view_cache_ctx.main_idx) ? '*' : ' ',
  593. view_cache_ctx.dsc->vlist[i]);
  594. }
  595. os_printk("\n\t cross:");
  596. for (; i < view_cache_ctx.dsc->num + 2; i++) {
  597. os_printk(" %c%u", (i == view_cache_ctx.focus_idx) ? '*' : ' ',
  598. view_cache_ctx.dsc->cross_vlist[i - view_cache_ctx.dsc->num]);
  599. }
  600. os_printk("\n\n");
  601. }
  602. static int _view_cache_set_focus(uint16_t view_id)
  603. {
  604. int8_t main_idx = _view_cache_get_main_idx(view_id);
  605. if (main_idx < 0)
  606. return -EINVAL;
  607. if (main_idx == view_cache_ctx.main_idx) {
  608. uint8_t main_create_flag = 0;
  609. if (view_cache_ctx.dsc->cross_vlist[0] != VIEW_INVALID_ID)
  610. ui_view_pause(view_cache_ctx.dsc->cross_vlist[0]);
  611. if (view_cache_ctx.dsc->cross_vlist[1] != VIEW_INVALID_ID)
  612. ui_view_pause(view_cache_ctx.dsc->cross_vlist[1]);
  613. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  614. main_create_flag = UI_CREATE_FLAG_NO_PRELOAD;
  615. #endif
  616. if (!_view_cache_load_main(view_cache_ctx.main_idx - 1, main_create_flag)) {
  617. _view_cache_set_attr_main(main_idx - 1, _view_cache_decide_attr_main(main_idx - 1), false);
  618. }
  619. return 0;
  620. }
  621. return _view_cache_set_focus_idx(main_idx, false);
  622. }
  623. static int _view_cache_set_focus_idx(int8_t main_idx, bool in_restore)
  624. {
  625. uint16_t view_id = view_cache_ctx.dsc->vlist[main_idx];
  626. int8_t prefocus_idx = view_cache_ctx.main_idx;
  627. bool rotate2 = (view_cache_ctx.rotate && view_cache_ctx.dsc->num == 2);
  628. uint8_t main_create_flag = 0;
  629. // save cur view, _view_cache_decide_attr() depends on the main_idx.
  630. view_cache_ctx.main_idx = main_idx;
  631. if (view_cache_ctx.dsc->cross_attached_view != VIEW_INVALID_ID) {
  632. uint8_t cross_attr[2] = { 0, 0 };
  633. if (view_id == view_cache_ctx.dsc->cross_attached_view) {
  634. cross_attr[0] = _view_cache_decide_attr_cross(view_cache_ctx.dsc->num);
  635. cross_attr[1] = _view_cache_decide_attr_cross(view_cache_ctx.dsc->num + 1);
  636. }
  637. _view_cache_set_attr(view_cache_ctx.dsc->num, cross_attr[0], in_restore, false);
  638. _view_cache_set_attr(view_cache_ctx.dsc->num + 1, cross_attr[1], in_restore, false);
  639. }
  640. // clear attr for old prev/next view
  641. _view_cache_set_attr_main(prefocus_idx - 1, 0, false);
  642. if (!rotate2)
  643. _view_cache_set_attr_main(prefocus_idx + 1, 0, false);
  644. // unload unused view
  645. _view_cache_unload_main(main_idx - 2, false);
  646. _view_cache_unload_main(main_idx + 2, false);
  647. // preload and show new cur view
  648. _view_cache_load_main(main_idx, UI_CREATE_FLAG_SHOW);
  649. // preload and set attr for new prev/next view
  650. #ifdef CONFIG_VIEW_SCROLL_MEM_LOWEST
  651. main_create_flag = UI_CREATE_FLAG_NO_PRELOAD;
  652. #endif
  653. _view_cache_load_main(main_idx - 1, main_create_flag);
  654. _view_cache_set_attr_main(main_idx - 1, _view_cache_decide_attr_main(main_idx - 1), false);
  655. if (!rotate2) {
  656. _view_cache_load_main(main_idx + 1, main_create_flag);
  657. _view_cache_set_attr_main(main_idx + 1, _view_cache_decide_attr_main(main_idx + 1), false);
  658. }
  659. return 0;
  660. }
  661. #endif /* CONFIG_VIEW_SCROLL_MEM_DEFAULT */