24 #include "ui_drawing.h" 25 #include "ui_drawing_soft.h" 33 #if DRAWING_DMA2D_BPP == 16 34 #define DRAWING_DMA2D_FORMAT DMA2D_RGB565 35 #elif DRAWING_DMA2D_BPP == 24 36 #define DRAWING_DMA2D_FORMAT DMA2D_RGB888 37 #elif DRAWING_DMA2D_BPP == 32 38 #define DRAWING_DMA2D_FORMAT DMA2D_ARGB8888 40 #error "Define 'DRAWING_DMA2D_BPP' is required (16, 24 or 32)" 49 typedef void (*t_drawing_notification)(
bool under_isr);
56 uint8_t* dest_address;
68 uint32_t src_dma2d_format;
77 static DMA2D_HandleTypeDef g_hdma2d;
82 static t_drawing_notification g_callback_notification;
88 static bool g_dma2d_running;
93 static void* g_dma2d_semaphore;
100 static inline void _drawing_dma2d_wait(
void) {
101 while(g_dma2d_running) {
102 LLUI_DISPLAY_IMPL_binarySemaphoreTake(g_dma2d_semaphore);
109 static inline void _drawing_dma2d_done(
void) {
110 g_dma2d_running =
false;
111 LLUI_DISPLAY_IMPL_binarySemaphoreGive(g_dma2d_semaphore,
true);
117 static inline uint8_t* _drawing_dma2d_adjust_address(uint8_t* address, uint32_t x, uint32_t y, uint32_t stride, uint32_t bpp) {
118 return address + ((((y * stride) + x) * bpp) / (uint32_t)8);
124 static inline void _drawing_dma2d_configure_alpha_image_data(MICROUI_GraphicsContext* gc, jint* alphaAndColor) {
126 *(alphaAndColor) <<= 24;
127 *(alphaAndColor) |= (gc->foreground_color & 0xffffff);
139 static inline void _cleanDCache(
void) {
140 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) 164 static bool _drawing_dma2d_is_image_compatible_with_dma2d(MICROUI_GraphicsContext* gc, MICROUI_Image* image, jint x_src, jint y_src, jint width, jint height, jint x_dest, jint y_dest, jint alpha,
DRAWING_DMA2D_blending_t* dma2d_blending_data){
166 bool is_dma2d_compatible =
true;
167 jint data_width = width;
168 jint data_x_src = x_src;
169 jint data_x_dest = x_dest;
171 switch(image->format) {
172 case MICROUI_IMAGE_FORMAT_RGB565:
173 dma2d_blending_data->src_dma2d_format = CM_RGB565;
174 dma2d_blending_data->src_bpp = 16;
176 case MICROUI_IMAGE_FORMAT_ARGB8888:
177 dma2d_blending_data->src_dma2d_format = CM_ARGB8888;
178 dma2d_blending_data->src_bpp = 32;
180 case MICROUI_IMAGE_FORMAT_RGB888:
181 dma2d_blending_data->src_dma2d_format = CM_RGB888;
182 dma2d_blending_data->src_bpp = 24;
184 case MICROUI_IMAGE_FORMAT_ARGB1555:
185 dma2d_blending_data->src_dma2d_format = CM_ARGB1555;
186 dma2d_blending_data->src_bpp = 16;
188 case MICROUI_IMAGE_FORMAT_ARGB4444:
189 dma2d_blending_data->src_dma2d_format = CM_ARGB4444;
190 dma2d_blending_data->src_bpp = 16;
192 case MICROUI_IMAGE_FORMAT_A4: {
195 jint xAlign = data_x_src & 1;
196 jint wAlign = data_width & 1;
202 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src + data_width, y_src, 1, height, data_x_dest + data_width, y_dest, alpha);
211 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src, y_src, 1, height, data_x_dest, y_dest, alpha);
215 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src + data_width, y_src, 1, height, data_x_dest + data_width, y_dest, alpha);
223 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src, y_src, 1, height, data_x_dest, y_dest, alpha);
230 _drawing_dma2d_configure_alpha_image_data(gc, &alpha);
231 dma2d_blending_data->src_dma2d_format = CM_A4;
232 dma2d_blending_data->src_bpp = 4;
235 case MICROUI_IMAGE_FORMAT_A8:
236 _drawing_dma2d_configure_alpha_image_data(gc, &alpha);
237 dma2d_blending_data->src_dma2d_format = CM_A8;
238 dma2d_blending_data->src_bpp = 8;
242 is_dma2d_compatible =
false;
246 if (is_dma2d_compatible){
247 MICROUI_Image* dest = &gc->image;
248 dma2d_blending_data->src_address = LLUI_DISPLAY_getBufferAddress(image);
249 dma2d_blending_data->dest_address = LLUI_DISPLAY_getBufferAddress(dest);
250 dma2d_blending_data->src_stride = LLUI_DISPLAY_getStrideInPixels(image);
251 dma2d_blending_data->dest_stride = LLUI_DISPLAY_getStrideInPixels(dest);
252 dma2d_blending_data->dest_width = dest->width;
253 dma2d_blending_data->dest_height = dest->height;
254 dma2d_blending_data->x_src = data_x_src;
255 dma2d_blending_data->y_src = y_src;
256 dma2d_blending_data->width = data_width;
257 dma2d_blending_data->height = height;
258 dma2d_blending_data->x_dest = data_x_dest;
259 dma2d_blending_data->y_dest = y_dest;
260 dma2d_blending_data->alpha = alpha;
265 return is_dma2d_compatible;
277 _drawing_dma2d_wait();
280 HAL_DMA2D_DeInit(&g_hdma2d);
283 g_hdma2d.LayerCfg[0].InputOffset = dma2d_blending_data->dest_stride - dma2d_blending_data->width;
284 g_hdma2d.LayerCfg[0].InputColorMode = DRAWING_DMA2D_FORMAT;
285 g_hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
286 g_hdma2d.LayerCfg[0].InputAlpha = 255;
287 HAL_DMA2D_ConfigLayer(&g_hdma2d, 0);
290 HAL_DMA2D_DisableCLUT(&g_hdma2d, 1);
291 g_hdma2d.LayerCfg[1].InputOffset = dma2d_blending_data->src_stride - dma2d_blending_data->width;
292 g_hdma2d.LayerCfg[1].InputColorMode = dma2d_blending_data->src_dma2d_format;
293 g_hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;
294 g_hdma2d.LayerCfg[1].InputAlpha = dma2d_blending_data->alpha;
295 HAL_DMA2D_ConfigLayer(&g_hdma2d, 1);
298 g_hdma2d.Init.Mode = DMA2D_M2M_BLEND;
299 g_hdma2d.Init.OutputOffset = dma2d_blending_data->dest_stride - dma2d_blending_data->width;
300 HAL_DMA2D_Init(&g_hdma2d) ;
303 g_callback_notification = &LLUI_DISPLAY_notifyAsynchronousDrawingEnd;
312 uint8_t* srcAddr = _drawing_dma2d_adjust_address(dma2d_blending_data->src_address, dma2d_blending_data->x_src, dma2d_blending_data->y_src, dma2d_blending_data->src_stride, dma2d_blending_data->src_bpp);
313 uint8_t* destAddr = _drawing_dma2d_adjust_address(dma2d_blending_data->dest_address, dma2d_blending_data->x_dest, dma2d_blending_data->y_dest, dma2d_blending_data->dest_stride, DRAWING_DMA2D_BPP);
314 g_dma2d_running =
true;
317 HAL_DMA2D_BlendingStart_IT(&g_hdma2d, (uint32_t)srcAddr, (uint32_t)destAddr, (uint32_t)destAddr, dma2d_blending_data->width, dma2d_blending_data->height);
330 jint width = dma2d_blending_data->width;
331 dma2d_blending_data->width = dma2d_blending_data->x_dest - dma2d_blending_data->x_src;
332 _drawing_dma2d_blending_configure(dma2d_blending_data);
335 dma2d_blending_data->x_src += width;
336 dma2d_blending_data->x_dest = dma2d_blending_data->x_src + dma2d_blending_data->width;
341 if (width < dma2d_blending_data->width){
342 dma2d_blending_data->width = width;
343 _drawing_dma2d_blending_configure(dma2d_blending_data);
347 dma2d_blending_data->x_src -= dma2d_blending_data->width;
348 dma2d_blending_data->x_dest -= dma2d_blending_data->width;
350 _drawing_dma2d_wait();
351 _drawing_dma2d_blending_start(dma2d_blending_data);
353 width -= dma2d_blending_data->width;
367 jint height = dma2d_blending_data->height;
368 dma2d_blending_data->height = dma2d_blending_data->y_dest - dma2d_blending_data->y_src;
369 _drawing_dma2d_blending_configure(dma2d_blending_data);
372 dma2d_blending_data->y_src += height;
373 dma2d_blending_data->y_dest = dma2d_blending_data->y_src + dma2d_blending_data->height;
378 if (height < dma2d_blending_data->height){
379 dma2d_blending_data->height = height;
384 dma2d_blending_data->y_src -= dma2d_blending_data->height;
385 dma2d_blending_data->y_dest -= dma2d_blending_data->height;
387 _drawing_dma2d_wait();
388 _drawing_dma2d_blending_start(dma2d_blending_data);
390 height -= dma2d_blending_data->height;
396 void DRAWING_DMA2D_IRQHandler(
void) {
398 HAL_DMA2D_IRQHandler(&g_hdma2d);
401 _drawing_dma2d_done();
404 g_callback_notification(
true);
409 void DRAWING_DMA2D_initialize(
void* binary_semaphore_handle) {
411 g_dma2d_running =
false;
412 g_dma2d_semaphore = binary_semaphore_handle;
415 HAL_NVIC_SetPriority(DMA2D_IRQn, 5, 3);
416 HAL_NVIC_EnableIRQ(DMA2D_IRQn);
419 g_hdma2d.Init.ColorMode = DRAWING_DMA2D_FORMAT;
420 g_hdma2d.Instance = DMA2D;
423 void DRAWING_DMA2D_configure_memcpy(uint8_t* srcAddr, uint8_t* destAddr, uint32_t xmin, uint32_t ymin, uint32_t xmax, uint32_t ymax, uint32_t stride,
DRAWING_DMA2D_memcpy* memcpy_data) {
424 _drawing_dma2d_wait();
426 uint32_t width = (xmax - xmin + (uint32_t)1);
427 uint32_t height = (ymax - ymin + (uint32_t)1);
430 HAL_DMA2D_DeInit(&g_hdma2d);
433 g_hdma2d.LayerCfg[1].InputOffset = stride - width;
434 g_hdma2d.LayerCfg[1].InputColorMode = DRAWING_DMA2D_FORMAT;
435 HAL_DMA2D_ConfigLayer(&g_hdma2d, 1);
438 g_hdma2d.Init.Mode = DMA2D_M2M;
439 g_hdma2d.Init.OutputOffset = stride - width;
440 HAL_DMA2D_Init(&g_hdma2d) ;
443 memcpy_data->src_address = _drawing_dma2d_adjust_address(srcAddr, xmin, ymin, stride, DRAWING_DMA2D_BPP);
444 memcpy_data->dest_address = _drawing_dma2d_adjust_address(destAddr, xmin, ymin, stride, DRAWING_DMA2D_BPP);
445 memcpy_data->width = width;
446 memcpy_data->height = height;
449 g_callback_notification = &LLUI_DISPLAY_flushDone;
450 g_dma2d_running =
true;
457 (uint32_t)memcpy_data->src_address,
458 (uint32_t)memcpy_data->dest_address,
466 DRAWING_Status UI_DRAWING_fillRectangle(MICROUI_GraphicsContext* gc, jint x1, jint y1, jint x2, jint y2) {
470 if (LLUI_DISPLAY_isClipEnabled(gc) && !LLUI_DISPLAY_clipRectangle(gc, &x1, &y1, &x2, &y2)) {
478 _drawing_dma2d_wait();
480 LLUI_DISPLAY_setDrawingLimits(x1, y1, x2, y2);
482 uint32_t rectangle_width = x2 - x1 + 1;
483 uint32_t rectangle_height = y2 - y1 + 1;
484 uint32_t stride = LLUI_DISPLAY_getStrideInPixels(&gc->image);
487 HAL_DMA2D_DeInit(&g_hdma2d);
490 g_hdma2d.Init.Mode = DMA2D_R2M;
491 g_hdma2d.Init.OutputOffset = stride - rectangle_width;
492 HAL_DMA2D_Init(&g_hdma2d);
495 g_callback_notification = &LLUI_DISPLAY_notifyAsynchronousDrawingEnd;
496 g_dma2d_running =
true;
500 uint8_t* destination_address = _drawing_dma2d_adjust_address(LLUI_DISPLAY_getBufferAddress(&gc->image), x1, y1, stride, DRAWING_DMA2D_BPP);
502 HAL_DMA2D_Start_IT(&g_hdma2d, gc->foreground_color, (uint32_t)destination_address, rectangle_width, rectangle_height);
504 ret = DRAWING_RUNNING;
510 DRAWING_Status UI_DRAWING_drawImage(MICROUI_GraphicsContext* gc, MICROUI_Image* image, jint x_src, jint y_src, jint width, jint height, jint x_dest, jint y_dest, jint alpha) {
515 if (_drawing_dma2d_is_image_compatible_with_dma2d(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha, &dma2d_blending_data)){
516 _drawing_dma2d_blending_configure(&dma2d_blending_data);
517 _drawing_dma2d_blending_start(&dma2d_blending_data);
518 ret = DRAWING_RUNNING;
521 UI_DRAWING_SOFT_drawImage(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha);
528 DRAWING_Status UI_DRAWING_drawRegion(MICROUI_GraphicsContext* gc, jint x_src, jint y_src, jint width, jint height, jint x_dest, jint y_dest, jint alpha){
533 if (_drawing_dma2d_is_image_compatible_with_dma2d(gc, &gc->image, x_src, y_src, width, height, x_dest, y_dest, alpha, &dma2d_blending_data)){
536 if ((dma2d_blending_data.y_dest == dma2d_blending_data.y_src) && (dma2d_blending_data.x_dest > dma2d_blending_data.x_src) && (dma2d_blending_data.x_dest < (dma2d_blending_data.x_src + dma2d_blending_data.width))){
538 _drawing_dma2d_overlap_horizontal(&dma2d_blending_data);
540 else if ((dma2d_blending_data.y_dest > dma2d_blending_data.y_src) && (dma2d_blending_data.y_dest < (dma2d_blending_data.y_src + dma2d_blending_data.height))){
542 _drawing_dma2d_overlap_vertical(&dma2d_blending_data);
546 _drawing_dma2d_blending_configure(&dma2d_blending_data);
547 _drawing_dma2d_blending_start(&dma2d_blending_data);
549 LLUI_DISPLAY_setDrawingLimits(dma2d_blending_data.x_dest, dma2d_blending_data.y_dest, dma2d_blending_data.x_dest + dma2d_blending_data.width - 1, dma2d_blending_data.y_dest + dma2d_blending_data.height - 1);
550 ret = DRAWING_RUNNING;
554 UI_DRAWING_SOFT_drawImage(gc, &gc->image, x_src, y_src, width, height, x_dest, y_dest, alpha);
Use STM32 DMA2D (ChromART) for MicroEJ ui_drawing.h implementation.