/* * Copyright (c) 2020 Actions Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief display surface interface */ #ifndef ZEPHYR_FRAMEWORK_INCLUDE_DISPLAY_UI_SURFACE_H_ #define ZEPHYR_FRAMEWORK_INCLUDE_DISPLAY_UI_SURFACE_H_ #include #include /** * @defgroup ui_surface_apis UI Surface APIs * @ingroup system_apis * @{ */ #ifdef __cplusplus extern "C" { #endif #ifdef CONFIG_SURFACE_DOUBLE_BUFFER # define CONFIG_SURFACE_MAX_BUFFER_COUNT (2) #elif defined(CONFIG_SURFACE_SINGLE_BUFFER) # define CONFIG_SURFACE_MAX_BUFFER_COUNT (1) #else # define CONFIG_SURFACE_MAX_BUFFER_COUNT (0) #endif /** * @enum surface_event_id * @brief Enumeration with possible surface event * */ enum surface_event_id { /* ready to accept next draw */ SURFACE_EVT_DRAW_READY = 0, /* check if current frame drawn dirty regions fully covers an area, * required to optimize the swapbuf copy in double buffer case. */ SURFACE_EVT_DRAW_COVER_CHECK, SURFACE_EVT_POST_START, }; /** * @enum surface_callback_id * @brief Enumeration with possible surface callback * */ enum surface_callback_id { SURFACE_CB_DRAW = 0, SURFACE_CB_POST, SURFACE_NUM_CBS, }; /** * @brief Enumeration with possible surface flags * */ enum { /* both for orientation and update flags */ SURFACE_ROTATED_90 = 0x01, SURFACE_ROTATED_180 = 0x02, SURFACE_ROTATED_270 = 0x03, SURFACE_ROTATED_MASK = 0x03, /* draw/update flags */ SURFACE_FIRST_DRAW = 0x10, /* first draw in one frame */ SURFACE_LAST_DRAW = 0x20, /* last draw in one frame */ /* post flags */ SURFACE_POST_IN_SYNC_MODE = 0x40, /* surface post in sync mode. */ }; /** * @struct surface_post_data * @brief Structure holding surface event data in callback SURFACE_CB_POST * */ typedef struct surface_post_data { uint8_t flags; const ui_region_t *area; } surface_post_data_t; /** * @struct surface_cover_check_data * @brief Structure holding surface event data in callback SURFACE_EVT_DRAW_COVER_CHECK * */ typedef struct surface_cover_check_data { const ui_region_t *area; bool covered; /* store the cover result with 'area' */ } surface_cover_check_data_t; /** * @typedef surface_callback_t * @brief Callback API executed when surface changed * */ typedef void (*surface_callback_t)(uint32_t event, void *data, void *user_data); /** * @struct surface * @brief Structure holding surface * */ typedef struct surface { uint16_t width; uint16_t height; uint32_t pixel_format; #if CONFIG_SURFACE_MAX_BUFFER_COUNT > 0 ui_region_t dirty_area; graphic_buffer_t *buffers[CONFIG_SURFACE_MAX_BUFFER_COUNT]; uint8_t buf_count; uint8_t draw_idx; uint8_t post_idx; uint8_t swapping : 1; #else graphic_buffer_t *buffers; uint8_t buf_count; uint8_t draw_idx; #endif /* CONFIG_SURFACE_MAX_BUFFER_COUNT > 0 */ uint8_t in_frame : 1; os_sem frame_sem; /* passed in surface_create() */ uint8_t create_flags; /* passed in surface_begin_draw() */ uint8_t draw_flags; atomic_t post_cnt; os_sem post_sem; surface_callback_t callback[SURFACE_NUM_CBS]; void *user_data[SURFACE_NUM_CBS]; /* reference count (considering alloc/free and post pending count) */ atomic_t refcount; } surface_t; /** * @brief Create surface buffer * * @param w width in pixels * @param h height in pixels * @param pixel_format display pixel format, see enum display_pixel_format * @param buffer usage * * @return pointer to graphic buffer structure; NULL if failed. */ graphic_buffer_t *surface_buffer_create(uint16_t w, uint16_t h, uint32_t pixel_format, uint32_t usage); /** * @brief Create surface * * Must be called in the draw thread context. * * @param w width in pixels * @param h height in pixels * @param pixel_format display pixel format, see enum display_pixel_format * @param buf_count number of buffers to allocate * @param flags surface create flags * * @return pointer to surface structure; NULL if failed. */ surface_t *surface_create(uint16_t w, uint16_t h, uint32_t pixel_format, uint8_t buf_count, uint8_t flags); /** * @brief Destroy surface * * Must be called in the draw thread context. * * @param surface pointer to surface structure * * @retval N/A. */ void surface_destroy(surface_t *surface); /** * @brief Register surface callback * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param callback event callback * @param user_data user data passed in callback function * * @return N/A. */ void surface_register_callback(surface_t *surface, int callback_id, surface_callback_t callback_fn, void *user_data); /** * @brief Set continuous draw count without waiting next draw ready. * * This is just a hint to surface. * Must call before the first draw. * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param count continuous draw count * * @retval 0 on success else negative error code. */ void surface_set_continuous_draw_count(surface_t *surface, uint8_t count); /** * @brief surface begin a new frame to draw. * * Must call when current frame dirty regions are computed, and before * any surface_begin_draw(). * * Must be called in the draw thread context. * * @param surface pointer to surface structure * * @return 0 on success else negetive errno code. */ int surface_begin_frame(surface_t *surface); /** * @brief surface end current frame to draw * * @param surface pointer to surface structure * * @return 0 on success else negetive errno code. */ int surface_end_frame(surface_t *surface); /** * @brief surface begin to draw the current frame * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param flags draw flags * @param drawbuf store the pointer of draw buffer. * * @retval 0 on success else negative error code. */ int surface_begin_draw(surface_t *surface, uint8_t flags, graphic_buffer_t **drawbuf); /** * @brief surface end to draw the current frame * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param area updated surface area * * @retval 0 on success else negative error code. */ int surface_end_draw(surface_t *surface, const ui_region_t *area); /** * @brief surface update with the external buffer * * @param surface pointer to surface structure * @param flags draw flags, can contain SURFACE_ROTATED_? if enabled. * @param area updated surface area after rotation if set * @param buf pointer to the data buffer before rotation if set * @param stride stride in pixels of the data buffer * @param pixel_format pixel format of the data buffer * * @retval 0 on success else negative error code. */ int surface_update(surface_t *surface, uint8_t flags, const ui_region_t *area, const void *buf, uint16_t stride, uint32_t pixel_format); /** * @brief wait the surface update content completed * * Wait the previous surface_update() completed * Must be called in the draw thread context. * * @param surface pointer to surface structure * @parem timeout wait timeout in milliseconds * * @retval 0 on success else negative error code. */ int surface_wait_for_update(surface_t *surface, int timeout); /** * @brief wait the surface refresh to display completed * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @parem timeout wait timeout in milliseconds * * @retval 0 on success else negative error code. */ int surface_wait_for_refresh(surface_t *surface, int timeout); /** * @brief notify surface that one post has completed * * This must be called once corresponding to every SURFACE_EVT_POST_START. * * @param surface pointer to surface structure * * @return N/A. */ void surface_complete_one_post(surface_t *surface); /** * @brief Get pixel format of surface * * @param surface pointer to surface structure * * @return pixel format. */ static inline uint32_t surface_get_pixel_format(surface_t *surface) { return surface->pixel_format; } /** * @brief Get width of surface * * @param surface pointer to surface structure * * @return width in pixels. */ static inline uint16_t surface_get_width(surface_t *surface) { return surface->width; } /** * @brief Get height of surface * * @param surface pointer to surface structure * * @return height in pixels. */ static inline uint16_t surface_get_height(surface_t *surface) { return surface->height; } /** * @brief Get stride of surface * * @param surface pointer to surface structure * * @return stride in pixels. */ static inline uint32_t surface_get_stride(surface_t *surface) { #if CONFIG_SURFACE_MAX_BUFFER_COUNT > 0 return surface->buffers[0] ? graphic_buffer_get_stride(surface->buffers[0]) : surface->width; #else return surface->width; #endif } /** * @brief Get orientation of surface * * @param surface pointer to surface structure * * @return rotation (CW) in degrees */ static inline uint16_t surface_get_orientation(surface_t *surface) { return ((surface->create_flags & SURFACE_ROTATED_90) ? 90 : 0) + ((surface->create_flags & SURFACE_ROTATED_180) ? 180 : 0); } /** * @brief Get allocated buffer count of surface * * @param surface pointer to surface structure * * @return buffer count of surface. */ uint8_t surface_get_buffer_count(surface_t *surface); /** * @brief Get maximum supported surface buffer count * * @return buffer count. */ uint8_t surface_get_max_possible_buffer_count(void); /** * @cond INTERNAL_HIDDEN */ /** * @brief Set minumum buffer count of surface * * It will check current buffer count, if it is less than min_count, * buffers will be allocated. * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param min_count min buffer count * * @retval 0 on success else negative code. */ int surface_set_min_buffer_count(surface_t *surface, uint8_t min_count); /** * @brief Set maximum buffer count of surface * * It will check current buffer count, if it is less than min_count, * buffers will be allocated. * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param max_count max buffer count * * @retval 0 on success else negative code. */ int surface_set_max_buffer_count(surface_t *surface, uint8_t max_count); /** * @brief Set current buffer count of surface * * Set buffer count, it will change the min/max buffer count if required. * * Must be called in the draw thread context. * * @param surface pointer to surface structure * @param buf_count buffer count * * @retval 0 on success else negative code. */ int surface_set_buffer_count(surface_t *surface, uint8_t buf_count); /** * @brief Get draw buffer of surface * * @param surface pointer to surface structure * * @return pointer of graphic buffer structure; NULL if failed. */ graphic_buffer_t *surface_get_draw_buffer(surface_t *surface); /** * @brief Get post buffer of surface * * @param surface pointer to surface structure * * @return pointer of graphic buffer structure; NULL if failed. */ graphic_buffer_t *surface_get_post_buffer(surface_t *surface); /** * INTERNAL_HIDDEN @endcond */ #ifdef __cplusplus } #endif /** * @} */ #endif /* ZEPHYR_FRAMEWORK_INCLUDE_DISPLAY_UI_SURFACE_H_ */