23 #include "ui_drawing_dma2d.h" 25 #include "ui_drawing_soft.h" 26 #include "ui_image_drawing.h" 35 #if DRAWING_DMA2D_BPP == 16 36 #define DRAWING_DMA2D_FORMAT DMA2D_RGB565 37 #elif DRAWING_DMA2D_BPP == 24 38 #define DRAWING_DMA2D_FORMAT DMA2D_RGB888 39 #elif DRAWING_DMA2D_BPP == 32 40 #define DRAWING_DMA2D_FORMAT DMA2D_ARGB8888 42 #error "Define 'DRAWING_DMA2D_BPP' is required (16, 24 or 32)" 48 #ifndef DRAWING_DMA2D_CACHE_MANAGEMENT 49 #error "Please define the DRAWING_DMA2D_CACHE_MANAGEMENT in drawing_dma2d_configuration.h" 59 typedef void (*t_drawing_notification)(
bool under_isr);
66 uint8_t* dest_address;
78 uint32_t src_dma2d_format;
89 static DMA2D_HandleTypeDef g_hdma2d;
94 static t_drawing_notification g_callback_notification;
100 static bool g_dma2d_running;
105 static void* g_dma2d_semaphore;
114 static inline void _drawing_dma2d_wait(
void) {
115 while(g_dma2d_running) {
116 LLUI_DISPLAY_IMPL_binarySemaphoreTake(g_dma2d_semaphore);
130 static inline void _invalidateDCache(
void) {
131 #if DRAWING_DMA2D_CACHE_MANAGEMENT == DRAWING_DMA2D_CACHE_MANAGEMENT_ENABLED 132 SCB_InvalidateDCache();
145 static inline void _cleanDCache(
void) {
146 #if DRAWING_DMA2D_CACHE_MANAGEMENT == DRAWING_DMA2D_CACHE_MANAGEMENT_ENABLED 154 static inline void _drawing_dma2d_done(
void) {
155 g_dma2d_running =
false;
157 LLUI_DISPLAY_IMPL_binarySemaphoreGive(g_dma2d_semaphore,
true);
163 static inline uint8_t* _drawing_dma2d_adjust_address(uint8_t* address, uint32_t x, uint32_t y, uint32_t stride, uint32_t bpp) {
165 return address + ((((y * stride) + x) * bpp) / (uint32_t)8);
171 static inline void _drawing_dma2d_configure_alpha_image_data(MICROUI_GraphicsContext* gc, jint* alphaAndColor) {
173 *(alphaAndColor) <<= 24;
174 *(alphaAndColor) |= (gc->foreground_color & 0xffffff);
196 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){
198 bool is_dma2d_compatible =
true;
199 jint data_width = width;
200 jint data_x_src = x_src;
201 jint data_x_dest = x_dest;
203 switch(image->format) {
204 case MICROUI_IMAGE_FORMAT_RGB565:
205 dma2d_blending_data->src_dma2d_format = CM_RGB565;
206 dma2d_blending_data->src_bpp = 16;
208 case MICROUI_IMAGE_FORMAT_ARGB8888:
209 dma2d_blending_data->src_dma2d_format = CM_ARGB8888;
210 dma2d_blending_data->src_bpp = 32;
212 case MICROUI_IMAGE_FORMAT_RGB888:
213 dma2d_blending_data->src_dma2d_format = CM_RGB888;
214 dma2d_blending_data->src_bpp = 24;
216 case MICROUI_IMAGE_FORMAT_ARGB1555:
217 dma2d_blending_data->src_dma2d_format = CM_ARGB1555;
218 dma2d_blending_data->src_bpp = 16;
220 case MICROUI_IMAGE_FORMAT_ARGB4444:
221 dma2d_blending_data->src_dma2d_format = CM_ARGB4444;
222 dma2d_blending_data->src_bpp = 16;
224 case MICROUI_IMAGE_FORMAT_A4: {
227 jint xAlign = data_x_src & 1;
228 jint wAlign = data_width & 1;
234 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src + data_width, y_src, 1, height, data_x_dest + data_width, y_dest, alpha);
243 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src, y_src, 1, height, data_x_dest, y_dest, alpha);
247 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src + data_width, y_src, 1, height, data_x_dest + data_width, y_dest, alpha);
255 UI_DRAWING_SOFT_drawImage(gc, image, data_x_src, y_src, 1, height, data_x_dest, y_dest, alpha);
262 _drawing_dma2d_configure_alpha_image_data(gc, &alpha);
263 dma2d_blending_data->src_dma2d_format = CM_A4;
264 dma2d_blending_data->src_bpp = 4;
267 case MICROUI_IMAGE_FORMAT_A8:
268 _drawing_dma2d_configure_alpha_image_data(gc, &alpha);
269 dma2d_blending_data->src_dma2d_format = CM_A8;
270 dma2d_blending_data->src_bpp = 8;
274 is_dma2d_compatible =
false;
278 if (is_dma2d_compatible){
279 MICROUI_Image* dest = &gc->image;
280 dma2d_blending_data->src_address = LLUI_DISPLAY_getBufferAddress(image);
281 dma2d_blending_data->dest_address = LLUI_DISPLAY_getBufferAddress(dest);
282 dma2d_blending_data->src_stride = LLUI_DISPLAY_getStrideInPixels(image);
283 dma2d_blending_data->dest_stride = LLUI_DISPLAY_getStrideInPixels(dest);
284 dma2d_blending_data->dest_width = dest->width;
285 dma2d_blending_data->dest_height = dest->height;
286 dma2d_blending_data->x_src = data_x_src;
287 dma2d_blending_data->y_src = y_src;
288 dma2d_blending_data->width = data_width;
289 dma2d_blending_data->height = height;
290 dma2d_blending_data->x_dest = data_x_dest;
291 dma2d_blending_data->y_dest = y_dest;
292 dma2d_blending_data->alpha = alpha;
297 return is_dma2d_compatible;
309 _drawing_dma2d_wait();
312 HAL_DMA2D_DeInit(&g_hdma2d);
315 g_hdma2d.LayerCfg[0].InputOffset = dma2d_blending_data->dest_stride - dma2d_blending_data->width;
316 g_hdma2d.LayerCfg[0].InputColorMode = DRAWING_DMA2D_FORMAT;
317 g_hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
318 g_hdma2d.LayerCfg[0].InputAlpha = 255;
319 HAL_DMA2D_ConfigLayer(&g_hdma2d, 0);
322 HAL_DMA2D_DisableCLUT(&g_hdma2d, 1);
323 g_hdma2d.LayerCfg[1].InputOffset = dma2d_blending_data->src_stride - dma2d_blending_data->width;
324 g_hdma2d.LayerCfg[1].InputColorMode = dma2d_blending_data->src_dma2d_format;
325 g_hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;
326 g_hdma2d.LayerCfg[1].InputAlpha = dma2d_blending_data->alpha;
327 HAL_DMA2D_ConfigLayer(&g_hdma2d, 1);
330 g_hdma2d.Init.Mode = DMA2D_M2M_BLEND;
331 g_hdma2d.Init.OutputOffset = dma2d_blending_data->dest_stride - dma2d_blending_data->width;
332 HAL_DMA2D_Init(&g_hdma2d) ;
335 g_callback_notification = &LLUI_DISPLAY_notifyAsynchronousDrawingEnd;
344 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);
345 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);
346 g_dma2d_running =
true;
349 HAL_DMA2D_BlendingStart_IT(&g_hdma2d, (uint32_t)srcAddr, (uint32_t)destAddr, (uint32_t)destAddr, dma2d_blending_data->width, dma2d_blending_data->height);
362 jint width = dma2d_blending_data->width;
363 dma2d_blending_data->width = dma2d_blending_data->x_dest - dma2d_blending_data->x_src;
364 _drawing_dma2d_blending_configure(dma2d_blending_data);
367 dma2d_blending_data->x_src += width;
368 dma2d_blending_data->x_dest = dma2d_blending_data->x_src + dma2d_blending_data->width;
373 if (width < dma2d_blending_data->width){
374 dma2d_blending_data->width = width;
375 _drawing_dma2d_blending_configure(dma2d_blending_data);
379 dma2d_blending_data->x_src -= dma2d_blending_data->width;
380 dma2d_blending_data->x_dest -= dma2d_blending_data->width;
382 _drawing_dma2d_wait();
383 _drawing_dma2d_blending_start(dma2d_blending_data);
385 width -= dma2d_blending_data->width;
399 jint height = dma2d_blending_data->height;
400 dma2d_blending_data->height = dma2d_blending_data->y_dest - dma2d_blending_data->y_src;
401 _drawing_dma2d_blending_configure(dma2d_blending_data);
404 dma2d_blending_data->y_src += height;
405 dma2d_blending_data->y_dest = dma2d_blending_data->y_src + dma2d_blending_data->height;
410 if (height < dma2d_blending_data->height){
411 dma2d_blending_data->height = height;
416 dma2d_blending_data->y_src -= dma2d_blending_data->height;
417 dma2d_blending_data->y_dest -= dma2d_blending_data->height;
419 _drawing_dma2d_wait();
420 _drawing_dma2d_blending_start(dma2d_blending_data);
422 height -= dma2d_blending_data->height;
431 void UI_DRAWING_DMA2D_IRQHandler(
void) {
433 HAL_DMA2D_IRQHandler(&g_hdma2d);
436 _drawing_dma2d_done();
439 g_callback_notification(
true);
447 void UI_DRAWING_DMA2D_initialize(
void* binary_semaphore_handle) {
449 g_dma2d_running =
false;
450 g_dma2d_semaphore = binary_semaphore_handle;
453 HAL_NVIC_SetPriority(DMA2D_IRQn, 5, 3);
454 HAL_NVIC_EnableIRQ(DMA2D_IRQn);
457 g_hdma2d.Init.ColorMode = DRAWING_DMA2D_FORMAT;
458 g_hdma2d.Instance = DMA2D;
462 void UI_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) {
463 _drawing_dma2d_wait();
465 uint32_t width = (xmax - xmin + (uint32_t)1);
466 uint32_t height = (ymax - ymin + (uint32_t)1);
469 HAL_DMA2D_DeInit(&g_hdma2d);
472 g_hdma2d.LayerCfg[1].InputOffset = stride - width;
473 g_hdma2d.LayerCfg[1].InputColorMode = DRAWING_DMA2D_FORMAT;
474 HAL_DMA2D_ConfigLayer(&g_hdma2d, 1);
477 g_hdma2d.Init.Mode = DMA2D_M2M;
478 g_hdma2d.Init.OutputOffset = stride - width;
479 HAL_DMA2D_Init(&g_hdma2d) ;
482 memcpy_data->src_address = _drawing_dma2d_adjust_address(srcAddr, xmin, ymin, stride, DRAWING_DMA2D_BPP);
483 memcpy_data->dest_address = _drawing_dma2d_adjust_address(destAddr, xmin, ymin, stride, DRAWING_DMA2D_BPP);
484 memcpy_data->width = width;
485 memcpy_data->height = height;
488 g_callback_notification = &LLUI_DISPLAY_flushDone;
489 g_dma2d_running =
true;
498 (uint32_t)(memcpy_data->src_address),
500 (uint32_t)(memcpy_data->dest_address),
512 DRAWING_Status UI_DRAWING_DMA2D_fillRectangle(MICROUI_GraphicsContext* gc, jint x1, jint y1, jint x2, jint y2) {
514 _drawing_dma2d_wait();
516 LLUI_DISPLAY_setDrawingLimits(x1, y1, x2, y2);
518 uint32_t rectangle_width = x2 - x1 + 1;
519 uint32_t rectangle_height = y2 - y1 + 1;
520 uint32_t stride = LLUI_DISPLAY_getStrideInPixels(&gc->image);
523 HAL_DMA2D_DeInit(&g_hdma2d);
526 g_hdma2d.Init.Mode = DMA2D_R2M;
527 g_hdma2d.Init.OutputOffset = stride - rectangle_width;
528 HAL_DMA2D_Init(&g_hdma2d);
531 g_callback_notification = &LLUI_DISPLAY_notifyAsynchronousDrawingEnd;
532 g_dma2d_running =
true;
536 uint8_t* destination_address = _drawing_dma2d_adjust_address(LLUI_DISPLAY_getBufferAddress(&gc->image), x1, y1, stride, DRAWING_DMA2D_BPP);
538 HAL_DMA2D_Start_IT(&g_hdma2d, gc->foreground_color, (uint32_t)destination_address, rectangle_width, rectangle_height);
540 return DRAWING_RUNNING;
544 DRAWING_Status UI_DRAWING_DMA2D_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) {
549 if (_drawing_dma2d_is_image_compatible_with_dma2d(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha, &dma2d_blending_data)){
550 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);
551 _drawing_dma2d_blending_configure(&dma2d_blending_data);
552 _drawing_dma2d_blending_start(&dma2d_blending_data);
553 ret = DRAWING_RUNNING;
556 #if !defined(LLUI_IMAGE_CUSTOM_FORMATS) 557 UI_DRAWING_SOFT_drawImage(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha);
560 ret = UI_IMAGE_DRAWING_draw(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha);
568 DRAWING_Status UI_DRAWING_DMA2D_copyImage(MICROUI_GraphicsContext* gc, MICROUI_Image* img, jint regionX, jint regionY, jint width, jint height, jint x, jint y){
569 return (img == &gc->image) ?
571 UI_DRAWING_DMA2D_drawRegion(gc, regionX, regionY, width, height, x, y, 0xff)
573 : UI_DRAWING_DMA2D_drawImage(gc, img, regionX, regionY, width, height, x, y, 0xff);
577 DRAWING_Status UI_DRAWING_DMA2D_drawRegion(MICROUI_GraphicsContext* gc, jint x_src, jint y_src, jint width, jint height, jint x_dest, jint y_dest, jint alpha){
582 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)){
585 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);
587 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))){
589 _drawing_dma2d_overlap_horizontal(&dma2d_blending_data);
591 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))){
593 _drawing_dma2d_overlap_vertical(&dma2d_blending_data);
597 _drawing_dma2d_blending_configure(&dma2d_blending_data);
598 _drawing_dma2d_blending_start(&dma2d_blending_data);
600 ret = DRAWING_RUNNING;
604 #if !defined(LLUI_IMAGE_CUSTOM_FORMATS) 605 UI_DRAWING_SOFT_drawImage(gc, &gc->image, x_src, y_src, width, height, x_dest, y_dest, alpha);
608 ret = UI_IMAGE_DRAWING_draw(gc, &gc->image, x_src, y_src, width, height, x_dest, y_dest, alpha);
This file provides the configuration of ui_drawing_dma2d.c.