1 /**
2  * @file lv_draw_dave2d_image.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_draw_dave2d.h"
10 #if LV_USE_DRAW_DAVE2D
11 
12 #include "../../lv_image_decoder_private.h"
13 #include "../../lv_draw_image_private.h"
14 
15 /*********************
16  *      DEFINES
17  *********************/
18 
19 /**********************
20  *      TYPEDEFS
21  **********************/
22 
23 /**********************
24  *  STATIC PROTOTYPES
25  **********************/
26 static void img_draw_core(lv_draw_unit_t * u_base, const lv_draw_image_dsc_t * draw_dsc,
27                           const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
28                           const lv_area_t * img_coords, const lv_area_t * clipped_img_area);
29 
30 /**********************
31  *  STATIC VARIABLES
32  **********************/
33 
34 /**********************
35  *      MACROS
36  **********************/
37 
38 /**********************
39  *   GLOBAL FUNCTIONS
40  **********************/
41 
lv_draw_dave2d_image(lv_draw_dave2d_unit_t * draw_unit,const lv_draw_image_dsc_t * draw_dsc,const lv_area_t * coords)42 void lv_draw_dave2d_image(lv_draw_dave2d_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
43                           const lv_area_t * coords)
44 {
45     if(!draw_dsc->tile) {
46         lv_draw_image_normal_helper((lv_draw_unit_t *)draw_unit, draw_dsc, coords, img_draw_core);
47     }
48     else {
49         lv_draw_image_tiled_helper((lv_draw_unit_t *)draw_unit, draw_dsc, coords, img_draw_core);
50     }
51 }
52 
53 /**********************
54  *   STATIC FUNCTIONS
55  **********************/
56 
img_draw_core(lv_draw_unit_t * u_base,const lv_draw_image_dsc_t * draw_dsc,const lv_image_decoder_dsc_t * decoder_dsc,lv_draw_image_sup_t * sup,const lv_area_t * img_coords,const lv_area_t * clipped_img_area)57 static void img_draw_core(lv_draw_unit_t * u_base, const lv_draw_image_dsc_t * draw_dsc,
58                           const lv_image_decoder_dsc_t * decoder_dsc, lv_draw_image_sup_t * sup,
59                           const lv_area_t * img_coords, const lv_area_t * clipped_img_area)
60 {
61 
62     lv_draw_dave2d_unit_t * u = (lv_draw_dave2d_unit_t *)u_base;
63 
64     (void)sup; //remove warning about unused parameter
65 
66     bool transformed = draw_dsc->rotation != 0 || draw_dsc->scale_x != LV_SCALE_NONE ||
67                        draw_dsc->scale_y != LV_SCALE_NONE ? true : false;
68 
69     const lv_draw_buf_t * decoded = decoder_dsc->decoded;
70     const uint8_t * src_buf = decoded->data;
71     const lv_image_header_t * header = &decoded->header;
72     uint32_t img_stride = decoded->header.stride;
73     lv_color_format_t cf = decoded->header.cf;
74     lv_area_t buffer_area;
75     lv_area_t draw_area;
76     lv_area_t clipped_area;
77     int32_t x;
78     int32_t y;
79     d2_u8 a_texture_op = d2_to_one;
80     d2_u8 r_texture_op = d2_to_copy;
81     d2_u8 g_texture_op = d2_to_copy;
82     d2_u8 b_texture_op = d2_to_copy;
83     d2_u8 current_fill_mode;
84     d2_u32 src_blend_mode;
85     d2_u32 dst_blend_mode;
86     void * p_intermediate_buf = NULL;
87 
88 #if LV_USE_OS
89     lv_result_t  status;
90     status = lv_mutex_lock(u->pd2Mutex);
91     LV_ASSERT(LV_RESULT_OK == status);
92 #endif
93 
94     buffer_area = u->base_unit.target_layer->buf_area;
95     draw_area = *img_coords;
96     clipped_area = *clipped_img_area;
97 
98     x = 0 - u->base_unit.target_layer->buf_area.x1;
99     y = 0 - u->base_unit.target_layer->buf_area.y1;
100 
101     lv_area_move(&draw_area, x, y);
102     lv_area_move(&buffer_area, x, y);
103     lv_area_move(&clipped_area, x, y);
104 
105     /* Generate render operations*/
106 #if D2_RENDER_EACH_OPERATION
107     d2_selectrenderbuffer(u->d2_handle, u->renderbuffer);
108 #endif
109 
110     current_fill_mode = d2_getfillmode(u->d2_handle);
111     a_texture_op      = d2_gettextureoperationa(u->d2_handle);
112     r_texture_op      = d2_gettextureoperationr(u->d2_handle);
113     g_texture_op      = d2_gettextureoperationg(u->d2_handle);
114     b_texture_op      = d2_gettextureoperationb(u->d2_handle);
115     src_blend_mode    = d2_getblendmodesrc(u->d2_handle);
116     dst_blend_mode    = d2_getblendmodedst(u->d2_handle);
117 
118 #if defined(RENESAS_CORTEX_M85)
119 #if (BSP_CFG_DCACHE_ENABLED)
120     d1_cacheblockflush(u->d2_handle, 0, src_buf,
121                        img_stride * header->h); //Stride is in bytes, not pixels/texels
122 #endif
123 #endif
124 
125     if(LV_COLOR_FORMAT_RGB565A8 == cf) {
126 
127         lv_point_t p1[4] = { //Points in clockwise order
128             {0, 0},
129             {header->w - 1, 0},
130             {header->w - 1, header->h - 1},
131             {0, header->h - 1},
132         };
133 
134         d2_s32 dxu1 = D2_FIX16(1);
135         d2_s32 dxv1 = D2_FIX16(0);
136         d2_s32 dyu1 = D2_FIX16(0);
137         d2_s32 dyv1 = D2_FIX16(1);
138 
139         uint32_t size = header->h * (header->w * lv_color_format_get_size(LV_COLOR_FORMAT_ARGB8888));
140         p_intermediate_buf = lv_malloc(size);
141 
142         d2_framebuffer(u->d2_handle,
143                        p_intermediate_buf,
144                        (d2_s32)header->w,
145                        (d2_u32)header->w,
146                        (d2_u32)header->h,
147                        lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(LV_COLOR_FORMAT_ARGB8888));
148 
149         d2_cliprect(u->d2_handle, (d2_border)0, (d2_border)0, (d2_border)header->w - 1,
150                     (d2_border)header->h - 1);
151 
152         d2_settexopparam(u->d2_handle, d2_cc_alpha, draw_dsc->opa, 0);
153 
154         d2_settextureoperation(u->d2_handle, d2_to_replace, d2_to_copy, d2_to_copy, d2_to_copy);
155 
156         d2_settexturemapping(u->d2_handle, D2_FIX4(p1[0].x), D2_FIX4(p1[0].y), D2_FIX16(0), D2_FIX16(0), dxu1, dxv1, dyu1,
157                              dyv1);
158         d2_settexturemode(u->d2_handle, d2_tm_filter);
159         d2_setfillmode(u->d2_handle, d2_fm_texture);
160 
161         d2_settexture(u->d2_handle, (void *)src_buf,
162                       (d2_s32)(img_stride / lv_color_format_get_size(LV_COLOR_FORMAT_RGB565)),
163                       header->w,  header->h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(LV_COLOR_FORMAT_RGB565));
164 
165         d2_setblendmode(u->d2_handle, d2_bm_one, d2_bm_zero);
166 
167         d2_renderquad(u->d2_handle,
168                       (d2_point)D2_FIX4(p1[0].x),
169                       (d2_point)D2_FIX4(p1[0].y),
170                       (d2_point)D2_FIX4(p1[1].x),
171                       (d2_point)D2_FIX4(p1[1].y),
172                       (d2_point)D2_FIX4(p1[2].x),
173                       (d2_point)D2_FIX4(p1[2].y),
174                       (d2_point)D2_FIX4(p1[3].x),
175                       (d2_point)D2_FIX4(p1[3].y),
176                       0);
177 
178         d2_setblendmode(u->d2_handle, d2_bm_zero, d2_bm_one); //Keep the RGB data in the intermediate buffer
179 
180         d2_setalphablendmode(u->d2_handle, d2_bm_one, d2_bm_zero);    //Write SRC alpha, i.e. A8 data
181 
182         d2_settextureoperation(u->d2_handle, d2_to_copy, d2_to_copy, d2_to_copy, d2_to_copy);
183 
184         d2_settexture(u->d2_handle, (void *)(src_buf +  header->h * (header->w * lv_color_format_get_size(
185                                                                          LV_COLOR_FORMAT_RGB565))),
186                       (d2_s32)(img_stride / lv_color_format_get_size(LV_COLOR_FORMAT_RGB565)),
187                       header->w,  header->h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(LV_COLOR_FORMAT_A8));
188 
189         d2_renderquad(u->d2_handle,
190                       (d2_point)D2_FIX4(p1[0].x),
191                       (d2_point)D2_FIX4(p1[0].y),
192                       (d2_point)D2_FIX4(p1[1].x),
193                       (d2_point)D2_FIX4(p1[1].y),
194                       (d2_point)D2_FIX4(p1[2].x),
195                       (d2_point)D2_FIX4(p1[2].y),
196                       (d2_point)D2_FIX4(p1[3].x),
197                       (d2_point)D2_FIX4(p1[3].y),
198                       0);
199 
200         cf = LV_COLOR_FORMAT_ARGB8888;
201         src_buf = p_intermediate_buf;
202         img_stride = header->w * lv_color_format_get_size(cf);
203 
204     }
205 
206     d2_framebuffer_from_layer(u->d2_handle, u->base_unit.target_layer);
207 
208     d2_cliprect(u->d2_handle, (d2_border)clipped_area.x1, (d2_border)clipped_area.y1, (d2_border)clipped_area.x2,
209                 (d2_border)clipped_area.y2);
210 
211     d2_settexopparam(u->d2_handle, d2_cc_alpha, draw_dsc->opa, 0);
212 
213     if(LV_COLOR_FORMAT_RGB565 == cf) {
214         d2_settextureoperation(u->d2_handle, d2_to_replace, d2_to_copy, d2_to_copy, d2_to_copy);
215     }
216     else { //Formats with an alpha channel,
217         d2_settextureoperation(u->d2_handle, d2_to_copy, d2_to_copy, d2_to_copy, d2_to_copy);
218     }
219 
220     if(LV_BLEND_MODE_NORMAL == draw_dsc->blend_mode) { /**< Simply mix according to the opacity value*/
221         d2_setblendmode(u->d2_handle, d2_bm_alpha, d2_bm_one_minus_alpha);  //direct linear blend
222     }
223     else if(LV_BLEND_MODE_ADDITIVE == draw_dsc->blend_mode) { /**< Add the respective color channels*/
224         /* TODO */
225         d2_setblendmode(u->d2_handle, d2_bm_alpha, d2_bm_one);  //Additive blending
226     }
227     else if(LV_BLEND_MODE_SUBTRACTIVE == draw_dsc->blend_mode) { /**< Subtract the foreground from the background*/
228         /* TODO */
229     }
230     else { //LV_BLEND_MODE_MULTIPLY,   /**< Multiply the foreground and background*/
231         /* TODO */
232     }
233 
234     lv_point_t p[4] = { //Points in clockwise order
235         {0, 0},
236         {header->w - 1, 0},
237         {header->w - 1, header->h - 1},
238         {0, header->h - 1},
239     };
240 
241     d2_settexture(u->d2_handle, (void *)src_buf,
242                   (d2_s32)(img_stride / lv_color_format_get_size(cf)),
243                   header->w,  header->h, lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(cf));
244 
245     d2_settexturemode(u->d2_handle, d2_tm_filter);
246     d2_setfillmode(u->d2_handle, d2_fm_texture);
247 
248     d2_s32 dxu = D2_FIX16(1);
249     d2_s32 dxv = D2_FIX16(0);
250     d2_s32 dyu = D2_FIX16(0);
251     d2_s32 dyv = D2_FIX16(1);
252 
253     if(transformed) {
254         lv_point_transform(&p[0], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true);
255         lv_point_transform(&p[1], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true);
256         lv_point_transform(&p[2], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true);
257         lv_point_transform(&p[3], draw_dsc->rotation, draw_dsc->scale_x, draw_dsc->scale_y, &draw_dsc->pivot, true);
258 
259         int32_t angle_limited = draw_dsc->rotation;
260         if(angle_limited > 3600) angle_limited -= 3600;
261         if(angle_limited < 0) angle_limited += 3600;
262 
263         int32_t angle_low = angle_limited / 10;
264 
265         if(0 != angle_low) {
266             /* LV_TRIGO_SHIFT is 15, so only need to shift by 1 to get 16:16 fixed point */
267             dxv = (d2_s32)((1 << 1) * lv_trigo_sin((int16_t)angle_low));
268             dxu = (d2_s32)((1 << 1) * lv_trigo_cos((int16_t)angle_low));
269             dyv = (d2_s32)((1 << 1) * lv_trigo_sin((int16_t)angle_low + 90));
270             dyu = (d2_s32)((1 << 1) * lv_trigo_cos((int16_t)angle_low + 90));
271         }
272 
273         if(LV_SCALE_NONE != draw_dsc->scale_x) {
274             dxu = (dxu * LV_SCALE_NONE) / draw_dsc->scale_x;
275             dxv = (dxv * LV_SCALE_NONE) / draw_dsc->scale_x;
276         }
277         if(LV_SCALE_NONE != draw_dsc->scale_y) {
278             dyu = (dyu * LV_SCALE_NONE) / draw_dsc->scale_y;
279             dyv = (dyv * LV_SCALE_NONE) / draw_dsc->scale_y;
280         }
281     }
282 
283     p[0].x += draw_area.x1;
284     p[0].y += draw_area.y1;
285     p[1].x += draw_area.x1;
286     p[1].y += draw_area.y1;
287     p[2].x += draw_area.x1;
288     p[2].y += draw_area.y1;
289     p[3].x += draw_area.x1;
290     p[3].y += draw_area.y1;
291 
292     d2_settexturemapping(u->d2_handle, D2_FIX4(p[0].x), D2_FIX4(p[0].y), D2_FIX16(0), D2_FIX16(0), dxu, dxv, dyu,  dyv);
293 
294     d2_renderquad(u->d2_handle,
295                   (d2_point)D2_FIX4(p[0].x),
296                   (d2_point)D2_FIX4(p[0].y),
297                   (d2_point)D2_FIX4(p[1].x),
298                   (d2_point)D2_FIX4(p[1].y),
299                   (d2_point)D2_FIX4(p[2].x),
300                   (d2_point)D2_FIX4(p[2].y),
301                   (d2_point)D2_FIX4(p[3].x),
302                   (d2_point)D2_FIX4(p[3].y),
303                   0);
304 
305     //
306     // Execute render operations
307     //
308 #if D2_RENDER_EACH_OPERATION
309     d2_executerenderbuffer(u->d2_handle, u->renderbuffer, 0);
310     d2_flushframe(u->d2_handle);
311 #endif
312 
313     d2_setfillmode(u->d2_handle, current_fill_mode);
314     d2_settextureoperation(u->d2_handle, a_texture_op, r_texture_op, g_texture_op, b_texture_op);
315     d2_setblendmode(u->d2_handle, src_blend_mode, dst_blend_mode);
316 
317     if(NULL != p_intermediate_buf) {
318         lv_free(p_intermediate_buf);
319     }
320 
321 #if LV_USE_OS
322     status = lv_mutex_unlock(u->pd2Mutex);
323     LV_ASSERT(LV_RESULT_OK == status);
324 #endif
325 
326 }
327 
328 #endif //LV_USE_DRAW_DAVE2D
329