/** * @file lv_draw_sw_utils.c * */ /********************* * INCLUDES *********************/ #include "lv_draw_sw_utils.h" #if LV_USE_DRAW_SW /********************* * DEFINES *********************/ #ifndef LV_DRAW_SW_RGB565_SWAP #define LV_DRAW_SW_RGB565_SWAP(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE90_ARGB8888 #define LV_DRAW_SW_ROTATE90_ARGB8888(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE180_ARGB8888 #define LV_DRAW_SW_ROTATE180_ARGB8888(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE270_ARGB8888 #define LV_DRAW_SW_ROTATE270_ARGB8888(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE90_RGB888 #define LV_DRAW_SW_ROTATE90_RGB888(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE180_RGB888 #define LV_DRAW_SW_ROTATE180_RGB888(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE270_RGB888 #define LV_DRAW_SW_ROTATE270_RGB888(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE90_RGB565 #define LV_DRAW_SW_ROTATE90_RGB565(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE180_RGB565 #define LV_DRAW_SW_ROTATE180_RGB565(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE270_RGB565 #define LV_DRAW_SW_ROTATE270_RGB565(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE90_L8 #define LV_DRAW_SW_ROTATE90_L8(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE180_L8 #define LV_DRAW_SW_ROTATE180_L8(...) LV_RESULT_INVALID #endif #ifndef LV_DRAW_SW_ROTATE270_L8 #define LV_DRAW_SW_ROTATE270_L8(...) LV_RESULT_INVALID #endif /********************** * TYPEDEFS **********************/ /********************** * STATIC PROTOTYPES **********************/ #if LV_DRAW_SW_SUPPORT_ARGB8888 || LV_DRAW_SW_SUPPORT_XRGB8888 static void rotate90_argb8888(const uint32_t * src, uint32_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); static void rotate180_argb8888(const uint32_t * src, uint32_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride); static void rotate270_argb8888(const uint32_t * src, uint32_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); #endif #if LV_DRAW_SW_SUPPORT_RGB888 static void rotate90_rgb888(const uint8_t * src, uint8_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); static void rotate180_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride); static void rotate270_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dst_stride); #endif #if LV_DRAW_SW_SUPPORT_RGB565 static void rotate90_rgb565(const uint16_t * src, uint16_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); static void rotate180_rgb565(const uint16_t * src, uint16_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride); static void rotate270_rgb565(const uint16_t * src, uint16_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); #endif #if LV_DRAW_SW_SUPPORT_L8 static void rotate90_l8(const uint8_t * src, uint8_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); static void rotate180_l8(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride); static void rotate270_l8(const uint8_t * src, uint8_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride); #endif /********************** * STATIC VARIABLES **********************/ /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ void lv_draw_sw_i1_to_argb8888(const void * buf_i1, void * buf_argb8888, uint32_t width, uint32_t height, uint32_t buf_i1_stride, uint32_t buf_argb8888_stride, uint32_t index0_color, uint32_t index1_color) { /*Extract the bits of I1 px_map and convert them to ARGB8888*/ const uint8_t * src = buf_i1; uint32_t * dst = buf_argb8888; uint32_t i1_row_byte_count = width / 8; for(uint32_t row = 0; row < height; row++) { uint32_t * dst_p = dst; for(uint32_t i = 0; i < i1_row_byte_count; i++) { /*From MSB to LSB (pixel 0 to pixel 7 in a byte)*/ for(int32_t bit = 7; bit >= 0; bit--) { *dst_p++ = ((src[i] >> bit) & 1) ? index1_color : index0_color; } } src += buf_i1_stride; dst += buf_argb8888_stride / 4; } } void lv_draw_sw_rgb565_swap(void * buf, uint32_t buf_size_px) { if(LV_DRAW_SW_RGB565_SWAP(buf, buf_size_px) == LV_RESULT_OK) return; uint32_t u32_cnt = buf_size_px / 2; uint16_t * buf16 = buf; uint32_t * buf32 = buf; while(u32_cnt >= 8) { buf32[0] = ((buf32[0] & 0xff00ff00) >> 8) | ((buf32[0] & 0x00ff00ff) << 8); buf32[1] = ((buf32[1] & 0xff00ff00) >> 8) | ((buf32[1] & 0x00ff00ff) << 8); buf32[2] = ((buf32[2] & 0xff00ff00) >> 8) | ((buf32[2] & 0x00ff00ff) << 8); buf32[3] = ((buf32[3] & 0xff00ff00) >> 8) | ((buf32[3] & 0x00ff00ff) << 8); buf32[4] = ((buf32[4] & 0xff00ff00) >> 8) | ((buf32[4] & 0x00ff00ff) << 8); buf32[5] = ((buf32[5] & 0xff00ff00) >> 8) | ((buf32[5] & 0x00ff00ff) << 8); buf32[6] = ((buf32[6] & 0xff00ff00) >> 8) | ((buf32[6] & 0x00ff00ff) << 8); buf32[7] = ((buf32[7] & 0xff00ff00) >> 8) | ((buf32[7] & 0x00ff00ff) << 8); buf32 += 8; u32_cnt -= 8; } while(u32_cnt) { *buf32 = ((*buf32 & 0xff00ff00) >> 8) | ((*buf32 & 0x00ff00ff) << 8); buf32++; u32_cnt--; } if(buf_size_px & 0x1) { uint32_t e = buf_size_px - 1; buf16[e] = ((buf16[e] & 0xff00) >> 8) | ((buf16[e] & 0x00ff) << 8); } } void lv_draw_sw_i1_invert(void * buf, uint32_t buf_size) { if(buf == NULL) return; uint8_t * byte_buf = (uint8_t *)buf; uint32_t i; /*Make the buffer aligned*/ while(((uintptr_t)(byte_buf) & (sizeof(int) - 1)) && buf_size > 0) { *byte_buf = ~(*byte_buf); byte_buf++; buf_size--; } if(buf_size >= sizeof(uint32_t)) { uint32_t * aligned_addr = (uint32_t *)byte_buf; uint32_t word_count = buf_size / 4; for(i = 0; i < word_count; ++i) { aligned_addr[i] = ~aligned_addr[i]; } byte_buf = (uint8_t *)(aligned_addr + word_count); buf_size = buf_size % sizeof(uint32_t); } for(i = 0; i < buf_size; ++i) { byte_buf[i] = ~byte_buf[i]; } } void lv_draw_sw_i1_convert_to_vtiled(const void * buf, uint32_t buf_size, uint32_t width, uint32_t height, void * out_buf, uint32_t out_buf_size, bool bit_order_lsb) { LV_ASSERT(buf && out_buf); LV_ASSERT(width % 8 == 0 && height % 8 == 0); LV_ASSERT(buf_size >= (width / 8) * height); LV_ASSERT(out_buf_size >= buf_size); lv_memset(out_buf, 0, out_buf_size); const uint8_t * src_buf = (uint8_t *)buf; uint8_t * dst_buf = (uint8_t *)out_buf; for(uint32_t y = 0; y < height; y++) { for(uint32_t x = 0; x < width; x++) { uint32_t src_index = y * width + x; uint32_t dst_index = x * height + y; uint8_t bit = (src_buf[src_index / 8] >> (7 - (src_index % 8))) & 0x01; if(bit_order_lsb) { dst_buf[dst_index / 8] |= (bit << (dst_index % 8)); } else { dst_buf[dst_index / 8] |= (bit << (7 - (dst_index % 8))); } } } } void lv_draw_sw_rotate(const void * src, void * dest, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dest_stride, lv_display_rotation_t rotation, lv_color_format_t color_format) { if(rotation == LV_DISPLAY_ROTATION_90) { switch(color_format) { #if LV_DRAW_SW_SUPPORT_L8 case LV_COLOR_FORMAT_L8: rotate90_l8(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_RGB565 case LV_COLOR_FORMAT_RGB565: rotate90_rgb565(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_RGB888 case LV_COLOR_FORMAT_RGB888: rotate90_rgb888(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_ARGB8888 || LV_DRAW_SW_SUPPORT_XRGB8888 case LV_COLOR_FORMAT_XRGB8888: case LV_COLOR_FORMAT_ARGB8888: rotate90_argb8888(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif default: break; } return; } if(rotation == LV_DISPLAY_ROTATION_180) { switch(color_format) { #if LV_DRAW_SW_SUPPORT_L8 case LV_COLOR_FORMAT_L8: rotate180_l8(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_RGB565 case LV_COLOR_FORMAT_RGB565: rotate180_rgb565(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_RGB888 case LV_COLOR_FORMAT_RGB888: rotate180_rgb888(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_ARGB8888 || LV_DRAW_SW_SUPPORT_XRGB8888 case LV_COLOR_FORMAT_XRGB8888: case LV_COLOR_FORMAT_ARGB8888: rotate180_argb8888(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif default: break; } return; } if(rotation == LV_DISPLAY_ROTATION_270) { switch(color_format) { #if LV_DRAW_SW_SUPPORT_L8 case LV_COLOR_FORMAT_L8: rotate270_l8(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_RGB565 case LV_COLOR_FORMAT_RGB565: rotate270_rgb565(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_RGB888 case LV_COLOR_FORMAT_RGB888: rotate270_rgb888(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif #if LV_DRAW_SW_SUPPORT_ARGB8888 || LV_DRAW_SW_SUPPORT_XRGB8888 case LV_COLOR_FORMAT_XRGB8888: case LV_COLOR_FORMAT_ARGB8888: rotate270_argb8888(src, dest, src_width, src_height, src_stride, dest_stride); break; #endif default: break; } return; } } /********************** * STATIC FUNCTIONS **********************/ #if LV_DRAW_SW_SUPPORT_ARGB8888 || LV_DRAW_SW_SUPPORT_XRGB8888 static void rotate270_argb8888(const uint32_t * src, uint32_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_ARGB8888(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } src_stride /= sizeof(uint32_t); dst_stride /= sizeof(uint32_t); for(int32_t x = 0; x < src_width; ++x) { int32_t dstIndex = x * dst_stride; int32_t srcIndex = x; for(int32_t y = 0; y < src_height; ++y) { dst[dstIndex + (src_height - y - 1)] = src[srcIndex]; srcIndex += src_stride; } } } static void rotate180_argb8888(const uint32_t * src, uint32_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride) { LV_UNUSED(dest_stride); if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_ARGB8888(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } src_stride /= sizeof(uint32_t); dest_stride /= sizeof(uint32_t); for(int32_t y = 0; y < height; ++y) { int32_t dstIndex = (height - y - 1) * dest_stride; int32_t srcIndex = y * src_stride; for(int32_t x = 0; x < width; ++x) { dst[dstIndex + width - x - 1] = src[srcIndex + x]; } } } static void rotate90_argb8888(const uint32_t * src, uint32_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_ARGB8888(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } src_stride /= sizeof(uint32_t); dst_stride /= sizeof(uint32_t); for(int32_t x = 0; x < src_width; ++x) { int32_t dstIndex = (src_width - x - 1); int32_t srcIndex = x; for(int32_t y = 0; y < src_height; ++y) { dst[dstIndex * dst_stride + y] = src[srcIndex]; srcIndex += src_stride; } } } #endif #if LV_DRAW_SW_SUPPORT_RGB888 static void rotate90_rgb888(const uint8_t * src, uint8_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_RGB888(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } for(int32_t x = 0; x < src_width; ++x) { for(int32_t y = 0; y < src_height; ++y) { int32_t srcIndex = y * src_stride + x * 3; int32_t dstIndex = (src_width - x - 1) * dst_stride + y * 3; dst[dstIndex] = src[srcIndex]; /*Red*/ dst[dstIndex + 1] = src[srcIndex + 1]; /*Green*/ dst[dstIndex + 2] = src[srcIndex + 2]; /*Blue*/ } } } static void rotate180_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_RGB888(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } for(int32_t y = 0; y < height; ++y) { for(int32_t x = 0; x < width; ++x) { int32_t srcIndex = y * src_stride + x * 3; int32_t dstIndex = (height - y - 1) * dest_stride + (width - x - 1) * 3; dst[dstIndex] = src[srcIndex]; dst[dstIndex + 1] = src[srcIndex + 1]; dst[dstIndex + 2] = src[srcIndex + 2]; } } } static void rotate270_rgb888(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_RGB888(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } for(int32_t x = 0; x < width; ++x) { for(int32_t y = 0; y < height; ++y) { int32_t srcIndex = y * src_stride + x * 3; int32_t dstIndex = x * dst_stride + (height - y - 1) * 3; dst[dstIndex] = src[srcIndex]; /*Red*/ dst[dstIndex + 1] = src[srcIndex + 1]; /*Green*/ dst[dstIndex + 2] = src[srcIndex + 2]; /*Blue*/ } } } #endif #if LV_DRAW_SW_SUPPORT_RGB565 static void rotate270_rgb565(const uint16_t * src, uint16_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_RGB565(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } src_stride /= sizeof(uint16_t); dst_stride /= sizeof(uint16_t); for(int32_t x = 0; x < src_width; ++x) { int32_t dstIndex = x * dst_stride; int32_t srcIndex = x; for(int32_t y = 0; y < src_height; ++y) { dst[dstIndex + (src_height - y - 1)] = src[srcIndex]; srcIndex += src_stride; } } } static void rotate180_rgb565(const uint16_t * src, uint16_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_RGB565(src, dst, width, height, src_stride)) { return ; } src_stride /= sizeof(uint16_t); dest_stride /= sizeof(uint16_t); for(int32_t y = 0; y < height; ++y) { int32_t dstIndex = (height - y - 1) * dest_stride; int32_t srcIndex = y * src_stride; for(int32_t x = 0; x < width; ++x) { dst[dstIndex + width - x - 1] = src[srcIndex + x]; } } } static void rotate90_rgb565(const uint16_t * src, uint16_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_RGB565(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } src_stride /= sizeof(uint16_t); dst_stride /= sizeof(uint16_t); for(int32_t x = 0; x < src_width; ++x) { int32_t dstIndex = (src_width - x - 1); int32_t srcIndex = x; for(int32_t y = 0; y < src_height; ++y) { dst[dstIndex * dst_stride + y] = src[srcIndex]; srcIndex += src_stride; } } } #endif #if LV_DRAW_SW_SUPPORT_L8 static void rotate90_l8(const uint8_t * src, uint8_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE270_L8(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } for(int32_t x = 0; x < src_width; ++x) { int32_t dstIndex = (src_width - x - 1); int32_t srcIndex = x; for(int32_t y = 0; y < src_height; ++y) { dst[dstIndex * dst_stride + y] = src[srcIndex]; srcIndex += src_stride; } } } static void rotate180_l8(const uint8_t * src, uint8_t * dst, int32_t width, int32_t height, int32_t src_stride, int32_t dest_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE180_L8(src, dst, width, height, src_stride)) { return ; } for(int32_t y = 0; y < height; ++y) { int32_t dstIndex = (height - y - 1) * dest_stride; int32_t srcIndex = y * src_stride; for(int32_t x = 0; x < width; ++x) { dst[dstIndex + width - x - 1] = src[srcIndex + x]; } } } static void rotate270_l8(const uint8_t * src, uint8_t * dst, int32_t src_width, int32_t src_height, int32_t src_stride, int32_t dst_stride) { if(LV_RESULT_OK == LV_DRAW_SW_ROTATE90_L8(src, dst, src_width, src_height, src_stride, dst_stride)) { return ; } for(int32_t x = 0; x < src_width; ++x) { int32_t dstIndex = x * dst_stride; int32_t srcIndex = x; for(int32_t y = 0; y < src_height; ++y) { dst[dstIndex + (src_height - y - 1)] = src[srcIndex]; srcIndex += src_stride; } } } #endif #endif /*LV_USE_DRAW_SW*/