feat(draw): add sw display rotate implementations

This commit is contained in:
Gabor Kiss-Vamosi
2023-11-27 11:46:23 +01:00
parent 6e36f71f57
commit a5c92ef298
5 changed files with 436 additions and 27 deletions

View File

@@ -44,6 +44,29 @@ static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
static int32_t evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit);
static void rotate90_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride);
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 srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride);
static void rotate90_rgb888(const uint8_t * src, uint8_t * dst, int32_t srcWidth, int32_t srcHeight, int32_t srcStride,
int32_t dstStride);
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 srcStride,
int32_t dstStride);
static void rotate90_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride);
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 srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride);
/**********************
* STATIC VARIABLES
**********************/
@@ -112,6 +135,58 @@ static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit)
#endif
}
void lv_draw_sw_rgb565_swap(void * buf, int32_t buf_size_px)
{
uint32_t u32_cnt = buf_size_px / 2;
uint16_t * buf16 = buf;
uint32_t * buf32 = buf;
while(u32_cnt >= 8) {
buf32[0] = ((uint32_t)(buf32[0] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[0] & 0x00ff00ff) << 8);
buf32[1] = ((uint32_t)(buf32[1] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[1] & 0x00ff00ff) << 8);
buf32[2] = ((uint32_t)(buf32[2] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[2] & 0x00ff00ff) << 8);
buf32[3] = ((uint32_t)(buf32[3] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[3] & 0x00ff00ff) << 8);
buf32[4] = ((uint32_t)(buf32[4] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[4] & 0x00ff00ff) << 8);
buf32[5] = ((uint32_t)(buf32[5] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[5] & 0x00ff00ff) << 8);
buf32[6] = ((uint32_t)(buf32[6] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[6] & 0x00ff00ff) << 8);
buf32[7] = ((uint32_t)(buf32[7] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[7] & 0x00ff00ff) << 8);
buf32 += 8;
u32_cnt -= 8;
}
while(u32_cnt) {
*buf32 = ((uint32_t)(*buf32 & 0xff00ff00) >> 8) + ((uint32_t)(*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_rotate(const void * src, void * dest, int32_t src_width, int32_t src_height, int32_t src_sride,
int32_t dest_stride, lv_display_rotation_t rotation, lv_color_format_t color_format)
{
uint32_t px_bpp = lv_color_format_get_bpp(color_format);
if(rotation == LV_DISPLAY_ROTATION_90) {
if(px_bpp == 16) rotate90_rgb565(src, dest, src_width, src_height, src_sride, dest_stride);
if(px_bpp == 24) rotate90_rgb888(src, dest, src_width, src_height, src_sride, dest_stride);
if(px_bpp == 32) rotate90_argb8888(src, dest, src_width, src_height, src_sride, dest_stride);
}
else if(rotation == LV_DISPLAY_ROTATION_180) {
if(px_bpp == 16) rotate180_rgb565(src, dest, src_width, src_height, src_sride, dest_stride);
if(px_bpp == 24) rotate180_rgb888(src, dest, src_width, src_height, src_sride, dest_stride);
if(px_bpp == 32) rotate180_argb8888(src, dest, src_width, src_height, src_sride, dest_stride);
}
else if(rotation == LV_DISPLAY_ROTATION_270) {
if(px_bpp == 16) rotate270_rgb565(src, dest, src_width, src_height, src_sride, dest_stride);
if(px_bpp == 24) rotate270_rgb888(src, dest, src_width, src_height, src_sride, dest_stride);
if(px_bpp == 32) rotate270_argb8888(src, dest, src_width, src_height, src_sride, dest_stride);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -292,37 +367,145 @@ static void execute_drawing(lv_draw_sw_unit_t * u)
}
void lv_draw_sw_rgb565_swap(void * buf, int32_t buf_size_px)
static void rotate90_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride)
{
uint32_t u32_cnt = buf_size_px / 2;
uint16_t * buf16 = buf;
uint32_t * buf32 = buf;
srcStride /= sizeof(uint32_t);
dstStride /= sizeof(uint32_t);
while(u32_cnt >= 8) {
buf32[0] = ((uint32_t)(buf32[0] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[0] & 0x00ff00ff) << 8);
buf32[1] = ((uint32_t)(buf32[1] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[1] & 0x00ff00ff) << 8);
buf32[2] = ((uint32_t)(buf32[2] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[2] & 0x00ff00ff) << 8);
buf32[3] = ((uint32_t)(buf32[3] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[3] & 0x00ff00ff) << 8);
buf32[4] = ((uint32_t)(buf32[4] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[4] & 0x00ff00ff) << 8);
buf32[5] = ((uint32_t)(buf32[5] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[5] & 0x00ff00ff) << 8);
buf32[6] = ((uint32_t)(buf32[6] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[6] & 0x00ff00ff) << 8);
buf32[7] = ((uint32_t)(buf32[7] & 0xff00ff00) >> 8) + ((uint32_t)(buf32[7] & 0x00ff00ff) << 8);
buf32 += 8;
u32_cnt -= 8;
for(int32_t x = 0; x < srcWidth; ++x) {
int32_t dstIndex = x * dstStride;
int32_t srcIndex = x;
for(int32_t y = 0; y < srcHeight; ++y) {
dst[dstIndex + (srcHeight - y - 1)] = src[srcIndex];
srcIndex += srcStride;
}
while(u32_cnt) {
*buf32 = ((uint32_t)(*buf32 & 0xff00ff00) >> 8) + ((uint32_t)(*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);
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)
{
src_stride /= sizeof(uint32_t);
dest_stride /= sizeof(uint32_t);
for(int32_t y = 0; y < height; ++y) {
int32_t dstIndex = (height - y - 1) * src_stride;
int32_t srcIndex = y * src_stride;
for(int32_t x = 0; x < width; ++x) {
dst[dstIndex + width - x - 1] = src[srcIndex + x];
}
}
}
return;
static void rotate270_argb8888(const uint32_t * src, uint32_t * dst, int32_t srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride)
{
srcStride /= sizeof(uint32_t);
dstStride /= sizeof(uint32_t);
for(int32_t x = 0; x < srcWidth; ++x) {
int32_t dstIndex = (srcWidth - x - 1);
int32_t srcIndex = x;
for(int32_t y = 0; y < srcHeight; ++y) {
dst[dstIndex * dstStride + y] = src[srcIndex];
srcIndex += srcStride;
}
}
}
static void rotate90_rgb888(const uint8_t * src, uint8_t * dst, int32_t srcWidth, int32_t srcHeight, int32_t srcStride,
int32_t dstStride)
{
for(int32_t x = 0; x < srcWidth; ++x) {
for(int32_t y = 0; y < srcHeight; ++y) {
int32_t srcIndex = y * srcStride + x * 3;
int32_t dstIndex = (srcWidth - x - 1) * dstStride + 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)
{
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 srcStride,
int32_t dstStride)
{
for(int32_t x = 0; x < width; ++x) {
for(int32_t y = 0; y < height; ++y) {
int32_t srcIndex = y * srcStride + x * 3;
int32_t dstIndex = x * dstStride + (height - y - 1) * 3;
dst[dstIndex] = src[srcIndex]; // Red
dst[dstIndex + 1] = src[srcIndex + 1]; // Green
dst[dstIndex + 2] = src[srcIndex + 2]; // Blue
}
}
}
static void rotate90_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride)
{
srcStride /= sizeof(uint16_t);
dstStride /= sizeof(uint16_t);
for(int32_t x = 0; x < srcWidth; ++x) {
int32_t dstIndex = x * dstStride;
int32_t srcIndex = x;
for(int32_t y = 0; y < srcHeight; ++y) {
dst[dstIndex + (srcHeight - y - 1)] = src[srcIndex];
srcIndex += srcStride;
}
}
}
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)
{
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 rotate270_rgb565(const uint16_t * src, uint16_t * dst, int32_t srcWidth, int32_t srcHeight,
int32_t srcStride,
int32_t dstStride)
{
srcStride /= sizeof(uint16_t);
dstStride /= sizeof(uint16_t);
for(int32_t x = 0; x < srcWidth; ++x) {
int32_t dstIndex = (srcWidth - x - 1);
int32_t srcIndex = x;
for(int32_t y = 0; y < srcHeight; ++y) {
dst[dstIndex * dstStride + y] = src[srcIndex];
srcIndex += srcStride;
}
}
}
#endif /*LV_USE_DRAW_SW*/

View File

@@ -97,6 +97,9 @@ void lv_draw_sw_vector(lv_draw_unit_t * draw_unit, const lv_draw_vector_task_dsc
*/
void lv_draw_sw_rgb565_swap(void * buf, int32_t buf_size_px);
void lv_draw_sw_rotate(const void * src, void * dest, int32_t src_width, int32_t src_height, int32_t src_sride,
int32_t dest_stride, lv_display_rotation_t rotation, lv_color_format_t color_format);
/***********************
* GLOBAL VARIABLES
***********************/

View File

@@ -87,7 +87,6 @@ void lv_draw_sw_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, c
while(end_angle >= 360) end_angle -= 360;
void * mask_list[4] = {0};
/*Create an angle mask*/
lv_draw_sw_mask_angle_param_t mask_angle_param;
lv_draw_sw_mask_angle_init(&mask_angle_param, dsc->center.x, dsc->center.y, start_angle, end_angle);

View File

@@ -0,0 +1,224 @@
#if LV_BUILD_TEST || 1
#include "../lvgl.h"
#include "unity/unity.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
void test_rotate90_RGB565(void)
{
uint16_t srcArray[3 * 2] = {
0x1110, 0x2220, 0x3330,
0x4440, 0x5550, 0x6660
};
uint16_t dstArray[2 * 3] = {0};
uint16_t expectedArray[2 * 3] = {
0x4440, 0x1110,
0x5550, 0x2220,
0x6660, 0x3330
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint16_t),
2 * sizeof(uint16_t),
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_RGB565);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_RGB565(void)
{
uint16_t srcArray[3 * 2] = {
0x1110, 0x2220, 0x3330,
0x4440, 0x5550, 0x6660
};
uint16_t dstArray[3 * 2] = {0};
uint16_t expectedArray[3 * 2] = {
0x6660, 0x5550, 0x4440,
0x3330, 0x2220, 0x1110,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint16_t),
3 * sizeof(uint16_t),
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_RGB565);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_RGB565(void)
{
uint16_t srcArray[3 * 2] = {
0x1110, 0x2220, 0x3330,
0x4440, 0x5550, 0x6660
};
uint16_t dstArray[2 * 3] = {0};
uint16_t expectedArray[2 * 3] = {
0x3330, 0x6660,
0x2220, 0x5550,
0x1110, 0x4440,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint16_t),
2 * sizeof(uint16_t),
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_RGB565);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate90_RGB888(void)
{
uint8_t srcArray[3 * 2 * 3] = {
0x11, 0x1A, 0x1B, 0x22, 0x2A, 0x2B, 0x33, 0x3A, 0x3B,
0x44, 0x4A, 0x4B, 0x55, 0x5A, 0x5B, 0x66, 0x6A, 0x6B
};
uint8_t dstArray[2 * 3 * 3] = {0};
uint8_t expectedArray[2 * 3 * 3] = {
0x33, 0x3A, 0x3B, 0x66, 0x6A, 0x6B,
0x22, 0x2A, 0x2B, 0x55, 0x5A, 0x5B,
0x11, 0x1A, 0x1B, 0x44, 0x4A, 0x4B,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * 3,
2 * 3,
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_RGB888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_RGB888(void)
{
uint8_t srcArray[3 * 2 * 3] = {
0x11, 0x1A, 0x1B, 0x22, 0x2A, 0x2B, 0x33, 0x3A, 0x3B,
0x44, 0x4A, 0x4B, 0x55, 0x5A, 0x5B, 0x66, 0x6A, 0x6B
};
uint8_t dstArray[3 * 2 * 3] = {0};
uint8_t expectedArray[3 * 2 * 3] = {
0x66, 0x6A, 0x6B, 0x55, 0x5A, 0x5B, 0x44, 0x4A, 0x4B,
0x33, 0x3A, 0x3B, 0x22, 0x2A, 0x2B, 0x11, 0x1A, 0x1B
};
lv_draw_sw_rotate(srcArray, dstArray,
2, 3,
2 * 3,
2 * 3,
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_RGB888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_RGB888(void)
{
uint8_t srcArray[3 * 2 * 3] = {
0x11, 0x1A, 0x1B, 0x22, 0x2A, 0x2B, 0x33, 0x3A, 0x3B,
0x44, 0x4A, 0x4B, 0x55, 0x5A, 0x5B, 0x66, 0x6A, 0x6B
};
uint8_t dstArray[2 * 3 * 3] = {0};
uint8_t expectedArray[2 * 3 * 3] = {
0x44, 0x4A, 0x4B, 0x11, 0x1A, 0x1B,
0x55, 0x5A, 0x5B, 0x22, 0x2A, 0x2B,
0x66, 0x6A, 0x6B, 0x33, 0x3A, 0x3B,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * 3,
2 * 3,
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_RGB888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate90_ARGB8888(void)
{
uint32_t srcArray[3 * 2] = {
0x111A1B1C, 0x222A2B2C, 0x333A3B3C,
0x444A4B4C, 0x555A5B5C, 0x666A6B6C
};
uint32_t dstArray[2 * 3] = {0};
uint32_t expectedArray[2 * 3] = {
0x444A4B4C, 0x111A1B1C,
0x555A5B5C, 0x222A2B2C,
0x666A6B6C, 0x333A3B3C
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint32_t),
2 * sizeof(uint32_t),
LV_DISPLAY_ROTATION_90,
LV_COLOR_FORMAT_ARGB8888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate180_ARGB8888(void)
{
uint32_t srcArray[3 * 2] = {
0xFF0000FF, 0xFF00FF00, // Row 1: Red, Green
0xFFFF0000, 0xFFFFFFFF, // Row 2: Blue, White
0xFF00FFFF, 0xFFFFFF00 // Row 3: Cyan, Yellow
};
uint32_t dstArray[3 * 2] = {0};
uint32_t expectedArray[3 * 2] = {
0xFFFFFF00, 0xFF00FFFF, // Rotated Row 1
0xFFFFFFFF, 0xFFFF0000, // Rotated Row 2
0xFF00FF00, 0xFF0000FF // Rotated Row 3
};
lv_draw_sw_rotate(srcArray, dstArray,
2, 3,
2 * sizeof(uint32_t),
2 * sizeof(uint32_t),
LV_DISPLAY_ROTATION_180,
LV_COLOR_FORMAT_ARGB8888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
void test_rotate270_ARGB8888(void)
{
uint32_t srcArray[3 * 2] = {
0x111A1B1C, 0x222A2B2C, 0x333A3B3C,
0x444A4B4C, 0x555A5B5C, 0x666A6B6C
};
uint32_t dstArray[2 * 3] = {0};
uint32_t expectedArray[2 * 3] = {
0x333A3B3C, 0x666A6B6C,
0x222A2B2C, 0x555A5B5C,
0x111A1B1C, 0x444A4B4C,
};
lv_draw_sw_rotate(srcArray, dstArray,
3, 2,
3 * sizeof(uint32_t),
2 * sizeof(uint32_t),
LV_DISPLAY_ROTATION_270,
LV_COLOR_FORMAT_ARGB8888);
TEST_ASSERT_EQUAL_UINT8_ARRAY(expectedArray, dstArray, sizeof(dstArray));
}
#endif

View File

@@ -128,7 +128,7 @@ static uint8_t screen_buf_xrgb8888[800 * 480 * 4];
static bool screenhot_compare(const char * fn_ref, const char * mode, uint8_t tolerance)
{
char fn_ref_full[512];
char fn_ref_full[256];
sprintf(fn_ref_full, "%s%s", REF_IMGS_PATH, fn_ref);
lv_refr_now(NULL);
@@ -186,11 +186,11 @@ static bool screenhot_compare(const char * fn_ref, const char * mode, uint8_t to
}
if(err) {
char fn_ref_no_ext[256];
char fn_ref_no_ext[128];
strcpy(fn_ref_no_ext, fn_ref);
fn_ref_no_ext[strlen(fn_ref_no_ext) - 4] = '\0';
char fn_err_full[512];
char fn_err_full[256];
sprintf(fn_err_full, "%s%s_err.png", REF_IMGS_PATH, fn_ref_no_ext);
write_png_file(screen_buf_xrgb8888, 800, 480, fn_err_full);