/** * @file lv_draw_dma2d_image.c * */ /********************* * INCLUDES *********************/ #include "lv_draw_dma2d_private.h" #if LV_USE_DRAW_DMA2D /********************* * DEFINES *********************/ /********************** * TYPEDEFS **********************/ /********************** * STATIC PROTOTYPES **********************/ /********************** * STATIC VARIABLES **********************/ /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ void lv_draw_dma2d_opaque_image(lv_draw_dma2d_unit_t * u, void * dest_first_pixel, lv_area_t * clipped_coords, int32_t dest_stride) { int32_t w = lv_area_get_width(clipped_coords); int32_t h = lv_area_get_height(clipped_coords); lv_draw_image_dsc_t * dsc = u->task_act->draw_dsc; lv_color_format_t output_cf = dsc->base.layer->color_format; lv_color_format_t image_cf = dsc->header.cf; lv_draw_dma2d_output_cf_t output_cf_dma2d = lv_draw_dma2d_cf_to_dma2d_output_cf(output_cf); uint32_t output_cf_size = LV_COLOR_FORMAT_GET_SIZE(output_cf); lv_draw_dma2d_fgbg_cf_t image_cf_dma2d = (lv_draw_dma2d_fgbg_cf_t) lv_draw_dma2d_cf_to_dma2d_output_cf(image_cf); uint32_t image_cf_size = LV_COLOR_FORMAT_GET_SIZE(image_cf); const lv_image_dsc_t * img_dsc = dsc->src; uint32_t image_stride = img_dsc->header.stride; if(image_stride == 0) image_stride = image_cf_size * img_dsc->header.w; #if LV_DRAW_DMA2D_CACHE lv_draw_dma2d_cache_area_t dest_area = { .first_byte = dest_first_pixel, .width_bytes = w * output_cf_size, .height = h, .stride = dest_stride }; lv_memcpy(&u->writing_area, &dest_area, sizeof(lv_draw_dma2d_cache_area_t)); if(lv_color_format_has_alpha(image_cf)) { /* make sure the background area DMA2D is blending is up-to-date in main memory */ lv_draw_dma2d_clean_cache(&dest_area); } #endif const void * image_first_byte = img_dsc->data + (image_stride * (clipped_coords->y1 - dsc->image_area.y1)) + (image_cf_size * (clipped_coords->x1 - dsc->image_area.x1)); #if LV_DRAW_DMA2D_CACHE lv_draw_dma2d_cache_area_t src_area = { .first_byte = image_first_byte, .width_bytes = w * image_cf_size, .height = h, .stride = image_stride }; /* make sure the image area is up-to-date in main memory for DMA2D */ lv_draw_dma2d_clean_cache(&src_area); #endif uint32_t output_offset = (dest_stride / output_cf_size) - w; lv_draw_dma2d_configuration_t conf = { .mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_PFC, .w = w, .h = h, .output_address = dest_first_pixel, .output_offset = output_offset, .output_cf = output_cf_dma2d, .fg_address = image_first_byte, .fg_offset = (image_stride / image_cf_size) - w, .fg_cf = image_cf_dma2d }; /* only process the background if the image might be transparent */ if(lv_color_format_has_alpha(image_cf)) { conf.mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING; conf.bg_address = dest_first_pixel; conf.bg_offset = output_offset; conf.bg_cf = output_cf_dma2d; } /* Alpha channel should be treated as 0xFF if the cf is XRGB */ if(image_cf == LV_COLOR_FORMAT_XRGB8888) { conf.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL; conf.fg_alpha = 0xff; } if(output_cf == LV_COLOR_FORMAT_XRGB8888) { conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL; conf.bg_alpha = 0xff; } lv_draw_dma2d_configure_and_start_transfer(&conf); } void lv_draw_dma2d_image(lv_draw_dma2d_unit_t * u, void * dest_first_pixel, lv_area_t * clipped_coords, int32_t dest_stride) { int32_t w = lv_area_get_width(clipped_coords); int32_t h = lv_area_get_height(clipped_coords); lv_draw_image_dsc_t * dsc = u->task_act->draw_dsc; lv_color_format_t output_cf = dsc->base.layer->color_format; lv_color_format_t image_cf = dsc->header.cf; lv_opa_t opa = dsc->opa; lv_draw_dma2d_output_cf_t output_cf_dma2d = lv_draw_dma2d_cf_to_dma2d_output_cf(output_cf); uint32_t output_cf_size = LV_COLOR_FORMAT_GET_SIZE(output_cf); lv_draw_dma2d_fgbg_cf_t image_cf_dma2d = (lv_draw_dma2d_fgbg_cf_t) lv_draw_dma2d_cf_to_dma2d_output_cf(image_cf); uint32_t image_cf_size = LV_COLOR_FORMAT_GET_SIZE(image_cf); const lv_image_dsc_t * img_dsc = dsc->src; uint32_t image_stride = img_dsc->header.stride; if(image_stride == 0) image_stride = image_cf_size * img_dsc->header.w; #if LV_DRAW_DMA2D_CACHE lv_draw_dma2d_cache_area_t dest_area = { .first_byte = dest_first_pixel, .width_bytes = w * output_cf_size, .height = h, .stride = dest_stride }; lv_memcpy(&u->writing_area, &dest_area, sizeof(lv_draw_dma2d_cache_area_t)); /* make sure the background area DMA2D is blending is up-to-date in main memory */ lv_draw_dma2d_clean_cache(&dest_area); #endif const void * image_first_byte = img_dsc->data + (image_stride * (clipped_coords->y1 - dsc->image_area.y1)) + (image_cf_size * (clipped_coords->x1 - dsc->image_area.x1)); #if LV_DRAW_DMA2D_CACHE lv_draw_dma2d_cache_area_t src_area = { .first_byte = image_first_byte, .width_bytes = w * image_cf_size, .height = h, .stride = image_stride }; /* make sure the image area is up-to-date in main memory for DMA2D */ lv_draw_dma2d_clean_cache(&src_area); #endif uint32_t output_offset = (dest_stride / output_cf_size) - w; lv_draw_dma2d_configuration_t conf = { .mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING, .w = w, .h = h, .output_address = dest_first_pixel, .output_offset = output_offset, .output_cf = output_cf_dma2d, .fg_address = image_first_byte, .fg_offset = (image_stride / image_cf_size) - w, .fg_cf = image_cf_dma2d, .fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_MULTIPLY_IMAGE_ALPHA_CHANNEL, .fg_alpha = opa, .bg_address = dest_first_pixel, .bg_offset = output_offset, .bg_cf = output_cf_dma2d, }; /* Alpha channel should be treated as 0xFF if the cf is XRGB */ if(image_cf == LV_COLOR_FORMAT_XRGB8888) { conf.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL; } if(output_cf == LV_COLOR_FORMAT_XRGB8888) { conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL; conf.bg_alpha = 0xff; } lv_draw_dma2d_configure_and_start_transfer(&conf); } /********************** * STATIC FUNCTIONS **********************/ #endif /*LV_USE_DRAW_DMA2D*/