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