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;
263 return is_dma2d_compatible;
275 _drawing_dma2d_wait();
278 HAL_DMA2D_DeInit(&g_hdma2d);
281 g_hdma2d.LayerCfg[0].InputOffset = dma2d_blending_data->dest_stride - dma2d_blending_data->width;
282 g_hdma2d.LayerCfg[0].InputColorMode = DRAWING_DMA2D_FORMAT;
283 g_hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
284 g_hdma2d.LayerCfg[0].InputAlpha = 255;
285 HAL_DMA2D_ConfigLayer(&g_hdma2d, 0);
288 HAL_DMA2D_DisableCLUT(&g_hdma2d, 1);
289 g_hdma2d.LayerCfg[1].InputOffset = dma2d_blending_data->src_stride - dma2d_blending_data->width;
290 g_hdma2d.LayerCfg[1].InputColorMode = dma2d_blending_data->src_dma2d_format;
291 g_hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;
292 g_hdma2d.LayerCfg[1].InputAlpha = dma2d_blending_data->alpha;
293 HAL_DMA2D_ConfigLayer(&g_hdma2d, 1);
296 g_hdma2d.Init.Mode = DMA2D_M2M_BLEND;
297 g_hdma2d.Init.OutputOffset = dma2d_blending_data->dest_stride - dma2d_blending_data->width;
298 HAL_DMA2D_Init(&g_hdma2d) ;
301 g_callback_notification = &LLUI_DISPLAY_notifyAsynchronousDrawingEnd;
310 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);
311 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);
312 g_dma2d_running =
true;
315 HAL_DMA2D_BlendingStart_IT(&g_hdma2d, (uint32_t)srcAddr, (uint32_t)destAddr, (uint32_t)destAddr, dma2d_blending_data->width, dma2d_blending_data->height);
328 jint width = dma2d_blending_data->width;
329 dma2d_blending_data->width = dma2d_blending_data->x_dest - dma2d_blending_data->x_src;
330 _drawing_dma2d_blending_configure(dma2d_blending_data);
333 dma2d_blending_data->x_src += width;
334 dma2d_blending_data->x_dest = dma2d_blending_data->x_src + dma2d_blending_data->width;
339 if (width < dma2d_blending_data->width){
340 dma2d_blending_data->width = width;
341 _drawing_dma2d_blending_configure(dma2d_blending_data);
345 dma2d_blending_data->x_src -= dma2d_blending_data->width;
346 dma2d_blending_data->x_dest -= dma2d_blending_data->width;
348 _drawing_dma2d_wait();
349 _drawing_dma2d_blending_start(dma2d_blending_data);
351 width -= dma2d_blending_data->width;
365 jint height = dma2d_blending_data->height;
366 dma2d_blending_data->height = dma2d_blending_data->y_dest - dma2d_blending_data->y_src;
367 _drawing_dma2d_blending_configure(dma2d_blending_data);
370 dma2d_blending_data->y_src += height;
371 dma2d_blending_data->y_dest = dma2d_blending_data->y_src + dma2d_blending_data->height;
376 if (height < dma2d_blending_data->height){
377 dma2d_blending_data->height = height;
382 dma2d_blending_data->y_src -= dma2d_blending_data->height;
383 dma2d_blending_data->y_dest -= dma2d_blending_data->height;
385 _drawing_dma2d_wait();
386 _drawing_dma2d_blending_start(dma2d_blending_data);
388 height -= dma2d_blending_data->height;
401 if (dma2d_blending_data->src_address == dma2d_blending_data->dest_address) {
404 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))){
405 _drawing_dma2d_overlap_horizontal(dma2d_blending_data);
407 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))){
408 _drawing_dma2d_overlap_vertical(dma2d_blending_data);
411 _drawing_dma2d_blending_configure(dma2d_blending_data);
412 _drawing_dma2d_blending_start(dma2d_blending_data);
416 _drawing_dma2d_blending_configure(dma2d_blending_data);
417 _drawing_dma2d_blending_start(dma2d_blending_data);
420 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);
424 #if DRAWING_DMA2D_BPP == 16 430 static void memcpy_16_ltr(uint16_t* destination,
const uint16_t* source, uint32_t num) {
431 for (
int i = 0; i < (int)num; ++i) {
432 destination[i] = source[i];
440 static void memcpy_16_rtl(uint16_t* destination,
const uint16_t* source, uint32_t num) {
441 for (
int i = (
int)num-1; i >= 0; --i) {
442 destination[i] = source[i];
450 static void _drawing_soft_copy_pixels(uint8_t* src8, uint32_t src_stride, uint8_t* dst8, uint32_t dst_stride, uint32_t src_x, uint32_t src_y,
451 uint32_t width, uint32_t dst_x, uint32_t dst_y,
bool rtl) {
454 uint16_t* dst = ((uint16_t*) dst8) + ((dst_y * dst_stride) + dst_x);
456 uint16_t* src = ((uint16_t*) src8) + ((src_y * src_stride) + src_x);
459 memcpy_16_rtl(dst, src, width);
461 memcpy_16_ltr(dst, src, width);
468 static void _drawing_soft_copy_region(MICROUI_Image* dest, MICROUI_Image* source, jint x_src, jint y_src, jint width, jint height, jint x_dest, jint y_dest) {
470 uint8_t* src = LLUI_DISPLAY_getBufferAddress(source);
471 uint8_t* dst = LLUI_DISPLAY_getBufferAddress(dest);
472 uint32_t src_stride = LLUI_DISPLAY_getStrideInPixels(source);
473 uint32_t dst_stride = LLUI_DISPLAY_getStrideInPixels(dest);
475 if (y_dest <= y_src) {
476 bool rtl = ((y_dest == y_src) && (x_dest > x_src));
477 for (
int dy = 0; dy < height; dy++) {
478 _drawing_soft_copy_pixels(src, src_stride, dst, dst_stride, x_src, y_src+dy, width, x_dest, y_dest+dy, rtl);
481 for (
int dy = height-1; dy >= 0; dy--) {
482 _drawing_soft_copy_pixels(src, src_stride, dst, dst_stride, x_src, y_src+dy, width, x_dest, y_dest+dy,
false);
486 LLUI_DISPLAY_setDrawingLimits(x_dest, y_dest, x_dest + width - 1, y_dest + height - 1);
489 #endif // DRAWING_DMA2D_BPP 504 static inline bool _is_useless_drawing(MICROUI_Image* dest, MICROUI_Image* source, jint x_src, jint y_src, jint x_dest, jint y_dest, jint alpha) {
505 return (dest == source) && (0xff == alpha) && (x_src == x_dest) && (y_src == y_dest);
510 void DRAWING_DMA2D_IRQHandler(
void) {
512 HAL_DMA2D_IRQHandler(&g_hdma2d);
515 _drawing_dma2d_done();
518 g_callback_notification(
true);
523 void DRAWING_DMA2D_initialize(
void* binary_semaphore_handle) {
525 g_dma2d_running =
false;
526 g_dma2d_semaphore = binary_semaphore_handle;
529 HAL_NVIC_SetPriority(DMA2D_IRQn, 5, 3);
530 HAL_NVIC_EnableIRQ(DMA2D_IRQn);
533 g_hdma2d.Init.ColorMode = DRAWING_DMA2D_FORMAT;
534 g_hdma2d.Instance = DMA2D;
537 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) {
538 _drawing_dma2d_wait();
540 uint32_t width = (xmax - xmin + (uint32_t)1);
541 uint32_t height = (ymax - ymin + (uint32_t)1);
544 HAL_DMA2D_DeInit(&g_hdma2d);
547 g_hdma2d.LayerCfg[1].InputOffset = stride - width;
548 g_hdma2d.LayerCfg[1].InputColorMode = DRAWING_DMA2D_FORMAT;
549 HAL_DMA2D_ConfigLayer(&g_hdma2d, 1);
552 g_hdma2d.Init.Mode = DMA2D_M2M;
553 g_hdma2d.Init.OutputOffset = stride - width;
554 HAL_DMA2D_Init(&g_hdma2d) ;
557 memcpy_data->src_address = _drawing_dma2d_adjust_address(srcAddr, xmin, ymin, stride, DRAWING_DMA2D_BPP);
558 memcpy_data->dest_address = _drawing_dma2d_adjust_address(destAddr, xmin, ymin, stride, DRAWING_DMA2D_BPP);
559 memcpy_data->width = width;
560 memcpy_data->height = height;
563 g_callback_notification = &LLUI_DISPLAY_flushDone;
564 g_dma2d_running =
true;
571 (uint32_t)memcpy_data->src_address,
572 (uint32_t)memcpy_data->dest_address,
580 DRAWING_Status UI_DRAWING_fillRectangle(MICROUI_GraphicsContext* gc, jint x1, jint y1, jint x2, jint y2) {
584 if (LLUI_DISPLAY_isClipEnabled(gc) && !LLUI_DISPLAY_clipRectangle(gc, &x1, &y1, &x2, &y2)) {
592 _drawing_dma2d_wait();
594 LLUI_DISPLAY_setDrawingLimits(x1, y1, x2, y2);
596 uint32_t rectangle_width = x2 - x1 + 1;
597 uint32_t rectangle_height = y2 - y1 + 1;
598 uint32_t stride = LLUI_DISPLAY_getStrideInPixels(&gc->image);
601 HAL_DMA2D_DeInit(&g_hdma2d);
604 g_hdma2d.Init.Mode = DMA2D_R2M;
605 g_hdma2d.Init.OutputOffset = stride - rectangle_width;
606 HAL_DMA2D_Init(&g_hdma2d);
609 g_callback_notification = &LLUI_DISPLAY_notifyAsynchronousDrawingEnd;
610 g_dma2d_running =
true;
614 uint8_t* destination_address = _drawing_dma2d_adjust_address(LLUI_DISPLAY_getBufferAddress(&gc->image), x1, y1, stride, DRAWING_DMA2D_BPP);
616 HAL_DMA2D_Start_IT(&g_hdma2d, gc->foreground_color, (uint32_t)destination_address, rectangle_width, rectangle_height);
618 ret = DRAWING_RUNNING;
624 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) {
627 if (!_is_useless_drawing(&gc->image, image, x_src, y_src, x_dest, y_dest, alpha)){
629 #if DRAWING_DMA2D_BPP == 16 630 if ((0xff == alpha) && (gc->image.format == image->format)) {
633 _drawing_soft_copy_region(&gc->image, image, x_src, y_src, width, height, x_dest, y_dest);
637 #endif // DRAWING_DMA2D_BPP 641 if (_drawing_dma2d_is_image_compatible_with_dma2d(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha, &dma2d_blending_data)){
642 _drawing_dma2d(&dma2d_blending_data);
643 ret = DRAWING_RUNNING;
646 UI_DRAWING_SOFT_drawImage(gc, image, x_src, y_src, width, height, x_dest, y_dest, alpha);
649 #if DRAWING_DMA2D_BPP == 16 651 #endif // DRAWING_DMA2D_BPP Use STM32 DMA2D (ChromART) for MicroEJ ui_drawing.h implementation.