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