1 /**
2  * @file lv_draw_dma2d_image.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "lv_draw_dma2d_private.h"
11 #if LV_USE_DRAW_DMA2D
12 
13 /*********************
14  *      DEFINES
15  *********************/
16 
17 /**********************
18  *      TYPEDEFS
19  **********************/
20 
21 /**********************
22  *  STATIC PROTOTYPES
23  **********************/
24 
25 /**********************
26  *  STATIC VARIABLES
27  **********************/
28 
29 /**********************
30  *      MACROS
31  **********************/
32 
33 /**********************
34  *   GLOBAL FUNCTIONS
35  **********************/
36 
lv_draw_dma2d_opaque_image(lv_draw_dma2d_unit_t * u,void * dest_first_pixel,lv_area_t * clipped_coords,int32_t dest_stride)37 void lv_draw_dma2d_opaque_image(lv_draw_dma2d_unit_t * u, void * dest_first_pixel, lv_area_t * clipped_coords,
38                                 int32_t dest_stride)
39 {
40     int32_t w = lv_area_get_width(clipped_coords);
41     int32_t h = lv_area_get_height(clipped_coords);
42 
43     lv_draw_image_dsc_t * dsc = u->task_act->draw_dsc;
44     lv_color_format_t output_cf = dsc->base.layer->color_format;
45     lv_color_format_t image_cf = dsc->header.cf;
46 
47     lv_draw_dma2d_output_cf_t output_cf_dma2d = lv_draw_dma2d_cf_to_dma2d_output_cf(output_cf);
48     uint32_t output_cf_size = LV_COLOR_FORMAT_GET_SIZE(output_cf);
49 
50     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);
51     uint32_t image_cf_size = LV_COLOR_FORMAT_GET_SIZE(image_cf);
52 
53     const lv_image_dsc_t * img_dsc = dsc->src;
54     uint32_t image_stride = img_dsc->header.stride;
55     if(image_stride == 0) image_stride = image_cf_size * img_dsc->header.w;
56 
57 #if LV_DRAW_DMA2D_CACHE
58     lv_draw_dma2d_cache_area_t dest_area = {
59         .first_byte = dest_first_pixel,
60         .width_bytes = w * output_cf_size,
61         .height = h,
62         .stride = dest_stride
63     };
64     lv_memcpy(&u->writing_area, &dest_area, sizeof(lv_draw_dma2d_cache_area_t));
65     if(lv_color_format_has_alpha(image_cf)) {
66         /* make sure the background area DMA2D is blending is up-to-date in main memory */
67         lv_draw_dma2d_clean_cache(&dest_area);
68     }
69 #endif
70 
71     const void * image_first_byte = img_dsc->data
72                                     + (image_stride * (clipped_coords->y1 - dsc->image_area.y1))
73                                     + (image_cf_size * (clipped_coords->x1 - dsc->image_area.x1));
74 
75 #if LV_DRAW_DMA2D_CACHE
76     lv_draw_dma2d_cache_area_t src_area = {
77         .first_byte = image_first_byte,
78         .width_bytes = w * image_cf_size,
79         .height = h,
80         .stride = image_stride
81     };
82     /* make sure the image area is up-to-date in main memory for DMA2D */
83     lv_draw_dma2d_clean_cache(&src_area);
84 #endif
85 
86     uint32_t output_offset = (dest_stride / output_cf_size) - w;
87     lv_draw_dma2d_configuration_t conf = {
88         .mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_PFC,
89         .w = w,
90         .h = h,
91 
92         .output_address = dest_first_pixel,
93         .output_offset = output_offset,
94         .output_cf = output_cf_dma2d,
95 
96         .fg_address = image_first_byte,
97         .fg_offset = (image_stride / image_cf_size) - w,
98         .fg_cf = image_cf_dma2d
99     };
100 
101     /* only process the background if the image might be transparent */
102     if(lv_color_format_has_alpha(image_cf)) {
103         conf.mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING;
104 
105         conf.bg_address = dest_first_pixel;
106         conf.bg_offset = output_offset;
107         conf.bg_cf = output_cf_dma2d;
108     }
109 
110     /* Alpha channel should be treated as 0xFF if the cf is XRGB */
111     if(image_cf == LV_COLOR_FORMAT_XRGB8888) {
112         conf.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
113         conf.fg_alpha = 0xff;
114     }
115     if(output_cf == LV_COLOR_FORMAT_XRGB8888) {
116         conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
117         conf.bg_alpha = 0xff;
118     }
119 
120     lv_draw_dma2d_configure_and_start_transfer(&conf);
121 }
122 
lv_draw_dma2d_image(lv_draw_dma2d_unit_t * u,void * dest_first_pixel,lv_area_t * clipped_coords,int32_t dest_stride)123 void lv_draw_dma2d_image(lv_draw_dma2d_unit_t * u, void * dest_first_pixel, lv_area_t * clipped_coords,
124                          int32_t dest_stride)
125 {
126     int32_t w = lv_area_get_width(clipped_coords);
127     int32_t h = lv_area_get_height(clipped_coords);
128 
129     lv_draw_image_dsc_t * dsc = u->task_act->draw_dsc;
130     lv_color_format_t output_cf = dsc->base.layer->color_format;
131     lv_color_format_t image_cf = dsc->header.cf;
132     lv_opa_t opa = dsc->opa;
133 
134     lv_draw_dma2d_output_cf_t output_cf_dma2d = lv_draw_dma2d_cf_to_dma2d_output_cf(output_cf);
135     uint32_t output_cf_size = LV_COLOR_FORMAT_GET_SIZE(output_cf);
136 
137     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);
138     uint32_t image_cf_size = LV_COLOR_FORMAT_GET_SIZE(image_cf);
139 
140     const lv_image_dsc_t * img_dsc = dsc->src;
141     uint32_t image_stride = img_dsc->header.stride;
142     if(image_stride == 0) image_stride = image_cf_size * img_dsc->header.w;
143 
144 #if LV_DRAW_DMA2D_CACHE
145     lv_draw_dma2d_cache_area_t dest_area = {
146         .first_byte = dest_first_pixel,
147         .width_bytes = w * output_cf_size,
148         .height = h,
149         .stride = dest_stride
150     };
151     lv_memcpy(&u->writing_area, &dest_area, sizeof(lv_draw_dma2d_cache_area_t));
152     /* make sure the background area DMA2D is blending is up-to-date in main memory */
153     lv_draw_dma2d_clean_cache(&dest_area);
154 #endif
155 
156     const void * image_first_byte = img_dsc->data
157                                     + (image_stride * (clipped_coords->y1 - dsc->image_area.y1))
158                                     + (image_cf_size * (clipped_coords->x1 - dsc->image_area.x1));
159 
160 #if LV_DRAW_DMA2D_CACHE
161     lv_draw_dma2d_cache_area_t src_area = {
162         .first_byte = image_first_byte,
163         .width_bytes = w * image_cf_size,
164         .height = h,
165         .stride = image_stride
166     };
167     /* make sure the image area is up-to-date in main memory for DMA2D */
168     lv_draw_dma2d_clean_cache(&src_area);
169 #endif
170 
171     uint32_t output_offset = (dest_stride / output_cf_size) - w;
172     lv_draw_dma2d_configuration_t conf = {
173         .mode = LV_DRAW_DMA2D_MODE_MEMORY_TO_MEMORY_WITH_BLENDING,
174         .w = w,
175         .h = h,
176 
177         .output_address = dest_first_pixel,
178         .output_offset = output_offset,
179         .output_cf = output_cf_dma2d,
180 
181         .fg_address = image_first_byte,
182         .fg_offset = (image_stride / image_cf_size) - w,
183         .fg_cf = image_cf_dma2d,
184         .fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_MULTIPLY_IMAGE_ALPHA_CHANNEL,
185         .fg_alpha = opa,
186 
187         .bg_address = dest_first_pixel,
188         .bg_offset = output_offset,
189         .bg_cf = output_cf_dma2d,
190     };
191 
192     /* Alpha channel should be treated as 0xFF if the cf is XRGB */
193     if(image_cf == LV_COLOR_FORMAT_XRGB8888) {
194         conf.fg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
195     }
196     if(output_cf == LV_COLOR_FORMAT_XRGB8888) {
197         conf.bg_alpha_mode = LV_DRAW_DMA2D_ALPHA_MODE_REPLACE_ALPHA_CHANNEL;
198         conf.bg_alpha = 0xff;
199     }
200 
201     lv_draw_dma2d_configure_and_start_transfer(&conf);
202 }
203 
204 /**********************
205  *   STATIC FUNCTIONS
206  **********************/
207 
208 #endif /*LV_USE_DRAW_DMA2D*/
209