1/**2* @file hal_disp.c3*4* @description HAL layer for display driver5*6*/78/*********************9* INCLUDES10*********************/11#include <stdint.h>12#include <stddef.h>13#include "../lv_hal/lv_hal_disp.h"14#include "../lv_misc/lv_mem.h"15#include "../lv_core/lv_obj.h"16#include "../lv_misc/lv_gc.h"1718#if defined(LV_GC_INCLUDE)19# include LV_GC_INCLUDE20#endif /* LV_ENABLE_GC */212223/*********************24* DEFINES25*********************/2627/**********************28* TYPEDEFS29**********************/3031/**********************32* STATIC PROTOTYPES33**********************/3435/**********************36* STATIC VARIABLES37**********************/38static lv_disp_t * active;3940/**********************41* MACROS42**********************/4344/**********************45* GLOBAL FUNCTIONS46**********************/4748/**49* Initialize a display driver with default values.50* It is used to surly have known values in the fields ant not memory junk.51* After it you can set the fields.52* @param driver pointer to driver variable to initialize53*/54void lv_disp_drv_init(lv_disp_drv_t * driver)55{56driver->disp_fill = NULL;57driver->disp_map = NULL;58driver->disp_flush = NULL;5960#if USE_LV_GPU61driver->mem_blend = NULL;62driver->mem_fill = NULL;63#endif6465#if LV_VDB_SIZE66driver->vdb_wr = NULL;67#endif68}6970/**71* Register an initialized display driver.72* Automatically set the first display as active.73* @param driver pointer to an initialized 'lv_disp_drv_t' variable (can be local variable)74* @return pointer to the new display or NULL on error75*/76lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)77{78lv_disp_t * node;7980node = lv_mem_alloc(sizeof(lv_disp_t));81lv_mem_assert(node);82if(node == NULL) return NULL;8384memcpy(&node->driver, driver, sizeof(lv_disp_drv_t));85node->next = NULL;8687/* Set first display as active by default */88if(LV_GC_ROOT(_lv_disp_list) == NULL) {89LV_GC_ROOT(_lv_disp_list) = node;90active = node;91lv_obj_invalidate(lv_scr_act());92} else {93((lv_disp_t*)LV_GC_ROOT(_lv_disp_list))->next = node;94}9596return node;97}9899100/**101* Set the active display102* @param disp pointer to a display (return value of 'lv_disp_register')103*/104void lv_disp_set_active(lv_disp_t * disp)105{106active = disp;107lv_obj_invalidate(lv_scr_act());108}109110/**111* Get a pointer to the active display112* @return pointer to the active display113*/114lv_disp_t * lv_disp_get_active(void)115{116return active;117}118119/**120* Get the next display.121* @param disp pointer to the current display. NULL to initialize.122* @return the next display or NULL if no more. Give the first display when the parameter is NULL123*/124lv_disp_t * lv_disp_next(lv_disp_t * disp)125{126if(disp == NULL) {127return LV_GC_ROOT(_lv_disp_list);128} else {129if(((lv_disp_t*)LV_GC_ROOT(_lv_disp_list))->next == NULL) return NULL;130else return ((lv_disp_t*)LV_GC_ROOT(_lv_disp_list))->next;131}132}133134/**135* Write the content of the internal buffer (VDB) to the display136* @param x1 left coordinate of the rectangle137* @param x2 right coordinate of the rectangle138* @param y1 top coordinate of the rectangle139* @param y2 bottom coordinate of the rectangle140* @param color_p fill color141*/142void lv_disp_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color)143{144if(active == NULL) return;145if(active->driver.disp_fill != NULL) active->driver.disp_fill(x1, y1, x2, y2, color);146}147148/**149* Fill a rectangular area with a color on the active display150* @param x1 left coordinate of the rectangle151* @param x2 right coordinate of the rectangle152* @param y1 top coordinate of the rectangle153* @param y2 bottom coordinate of the rectangle154* @param color_p pointer to an array of colors155*/156void lv_disp_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t * color_p)157{158if(active == NULL) return;159if(active->driver.disp_flush != NULL) {160161LV_LOG_TRACE("disp flush started");162active->driver.disp_flush(x1, y1, x2, y2, color_p);163LV_LOG_TRACE("disp flush ready");164165} else {166LV_LOG_WARN("disp flush function registered");167}168}169170/**171* Put a color map to a rectangular area on the active display172* @param x1 left coordinate of the rectangle173* @param x2 right coordinate of the rectangle174* @param y1 top coordinate of the rectangle175* @param y2 bottom coordinate of the rectangle176* @param color_map pointer to an array of colors177*/178void lv_disp_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_map)179{180if(active == NULL) return;181if(active->driver.disp_map != NULL) active->driver.disp_map(x1, y1, x2, y2, color_map);182}183184#if USE_LV_GPU185186/**187* Blend pixels to a destination memory from a source memory188* In 'lv_disp_drv_t' 'mem_blend' is optional. (NULL if not available)189* @param dest a memory address. Blend 'src' here.190* @param src pointer to pixel map. Blend it to 'dest'.191* @param length number of pixels in 'src'192* @param opa opacity (0, LV_OPA_TRANSP: transparent ... 255, LV_OPA_COVER, fully cover)193*/194void lv_disp_mem_blend(lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa)195{196if(active == NULL) return;197if(active->driver.mem_blend != NULL) active->driver.mem_blend(dest, src, length, opa);198}199200/**201* Fill a memory with a color (GPUs may support it)202* In 'lv_disp_drv_t' 'mem_fill' is optional. (NULL if not available)203* @param dest a memory address. Copy 'src' here.204* @param src pointer to pixel map. Copy it to 'dest'.205* @param length number of pixels in 'src'206* @param opa opacity (0, LV_OPA_TRANSP: transparent ... 255, LV_OPA_COVER, fully cover)207*/208void lv_disp_mem_fill(lv_color_t * dest, uint32_t length, lv_color_t color)209{210if(active == NULL) return;211if(active->driver.mem_fill != NULL) active->driver.mem_fill(dest, length, color);212}213214/**215* Shows if memory blending (by GPU) is supported or not216* @return false: 'mem_blend' is not supported in the driver; true: 'mem_blend' is supported in the driver217*/218bool lv_disp_is_mem_blend_supported(void)219{220if(active == NULL) return false;221if(active->driver.mem_blend) return true;222else return false;223}224225/**226* Shows if memory fill (by GPU) is supported or not227* @return false: 'mem_fill' is not supported in the drover; true: 'mem_fill' is supported in the driver228*/229bool lv_disp_is_mem_fill_supported(void)230{231if(active == NULL) return false;232if(active->driver.mem_fill) return true;233else return false;234}235236#endif237238/**********************239* STATIC FUNCTIONS240**********************/241242243244