Files
luban-lite-t3e-pro/packages/artinchip/lvgl-ui/lvgl_v8/lv_drivers/lv_ge2d.c
2025-09-30 11:56:06 +08:00

982 lines
32 KiB
C

/*
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Ning Fang <ning.fang@artinchip.com>
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <math.h>
#include <aic_core.h>
#include "lv_refr.h"
#include "lv_ge2d.h"
#include "mpp_ge.h"
#include "mpp_decoder.h"
#include "mpp_fb.h"
#include "aic_ui.h"
#include "aic_time.h"
#include "lv_fbdev.h"
#define PI 3.141592653589
#define SIN(x) (sin((x)* PI / 180.0))
#define COS(x) (cos((x)* PI / 180.0))
#define ALIGN_1024B(x) ((x+1023) & (~1023))
typedef struct _img_info {
uint32_t img_size;
int type;
lv_fs_file_t fp;
} img_info;
static struct mpp_ge *g_ge = NULL;
void lv_draw_aic_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc);
lv_res_t lv_draw_aic_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const void *src);
LV_ATTRIBUTE_FAST_MEM void lv_draw_aic_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords,
const uint8_t *src_buf, lv_img_cf_t cf);
static inline void rgb565_to_argb(unsigned short src_pixel, unsigned int* dst_color)
{
unsigned int a, r, g, b;
a = 0xff;
r = ((src_pixel & 0xf800) >> 8);
g = (src_pixel & 0x07e0) >> 3;
b = (src_pixel & 0x1f) << 3;
*dst_color = (a << 24) | ((r | (r >> 5)) << 16) |
((g | (g >> 6)) << 8) | (b | (b >> 5));
}
static img_info *img_info_init(const char *src)
{
char *ptr;
lv_fs_res_t res;
ptr = strrchr(src, '.');
if (!ptr) {
LV_LOG_ERROR("unknow img format:%s", src);
return NULL;
}
img_info *imginfo = (img_info *)malloc(sizeof(img_info));
if (!imginfo) {
LV_LOG_ERROR("src ops malloc fail \n");
return NULL;
}
if (!strcasecmp(ptr, ".jpg") || !strcasecmp(ptr, ".jpeg"))
imginfo->type = 0;
else if (!strcasecmp(ptr, ".png"))
imginfo->type = 1;
else
imginfo->type = -1;
if (imginfo->type == -1) {
LV_LOG_ERROR("src path%s\n", src);
free(imginfo);
return NULL;
}
res = lv_fs_open(&(imginfo->fp), src, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
LV_LOG_ERROR("img fs open fail \n");
free(imginfo);
return NULL;
}
lv_fs_seek(&(imginfo->fp), 0, SEEK_END);
lv_fs_tell(&(imginfo->fp), &(imginfo->img_size));
lv_fs_seek(&(imginfo->fp), 0, SEEK_SET);
return imginfo;
}
static int img_info_deinit(img_info *imginfo)
{
if (!imginfo)
return -1;
lv_fs_close(&(imginfo->fp));
free(imginfo);
return 0;
}
void lv_draw_aic_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
lv_draw_sw_init_ctx(drv, draw_ctx);
lv_draw_aic_ctx_t * aic_draw_ctx = (lv_draw_aic_ctx_t *)draw_ctx;
g_ge = mpp_ge_open();
if (!g_ge) {
LV_LOG_WARN("open ge device fail\n");
}
aic_draw_ctx->blend = lv_draw_aic_blend;
aic_draw_ctx->base_draw.draw_img = lv_draw_aic_draw_img;
aic_draw_ctx->base_draw.draw_img_decoded = lv_draw_aic_img_decoded;
return;
}
void lv_draw_aic_ctx_deinit(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx)
{
if (g_ge) {
mpp_ge_close(g_ge);
}
LV_UNUSED(drv);
LV_UNUSED(draw_ctx);
}
static inline bool is_rgb(enum mpp_pixel_format format)
{
switch (format) {
case MPP_FMT_ARGB_8888:
case MPP_FMT_ABGR_8888:
case MPP_FMT_RGBA_8888:
case MPP_FMT_BGRA_8888:
case MPP_FMT_XRGB_8888:
case MPP_FMT_XBGR_8888:
case MPP_FMT_RGBX_8888:
case MPP_FMT_BGRX_8888:
case MPP_FMT_RGB_888:
case MPP_FMT_BGR_888:
case MPP_FMT_ARGB_1555:
case MPP_FMT_ABGR_1555:
case MPP_FMT_RGBA_5551:
case MPP_FMT_BGRA_5551:
case MPP_FMT_RGB_565:
case MPP_FMT_BGR_565:
case MPP_FMT_ARGB_4444:
case MPP_FMT_ABGR_4444:
case MPP_FMT_RGBA_4444:
case MPP_FMT_BGRA_4444:
return true;
default:
break;
}
return false;
}
static void transform_upscaled(const lv_draw_img_dsc_t *draw_dsc, int32_t xin,
int32_t yin, int32_t * xout, int32_t * yout)
{
int32_t pivot_x_256 = draw_dsc->pivot.x * 256;
int32_t pivot_y_256 = draw_dsc->pivot.y * 256;
int32_t zoom = (256 * 256) / draw_dsc->zoom;
xin -= draw_dsc->pivot.x;
yin -= draw_dsc->pivot.y;
if (draw_dsc->angle == 0) {
*xout = (int32_t)(xin * zoom) + pivot_x_256;
*yout = (int32_t)(yin * zoom) + pivot_y_256;
} else {
int32_t sinma;
int32_t cosma;
int32_t angle = -draw_dsc->angle;
int32_t angle_low = angle / 10;
int32_t angle_high = angle_low + 1;
int32_t angle_rem = angle - (angle_low * 10);
int32_t s1 = lv_trigo_sin(angle_low);
int32_t s2 = lv_trigo_sin(angle_high);
int32_t c1 = lv_trigo_sin(angle_low + 90);
int32_t c2 = lv_trigo_sin(angle_high + 90);
sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10;
cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10;
sinma = sinma >> (LV_TRIGO_SHIFT - 10);
cosma = cosma >> (LV_TRIGO_SHIFT - 10);
if (zoom == LV_IMG_ZOOM_NONE) {
*xout = ((cosma * xin - sinma * yin) >> 2) + (pivot_x_256);
*yout = ((sinma * xin + cosma * yin) >> 2) + (pivot_y_256);
} else {
*xout = (((cosma * xin - sinma * yin) * zoom) >> 10) + (pivot_x_256);
*yout = (((sinma * xin + cosma * yin) * zoom) >> 10) + (pivot_y_256);
}
}
}
static void lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t x1, lv_coord_t y1,
lv_coord_t x2, lv_coord_t y2,
int16_t angle, uint16_t zoom,
const lv_point_t * pivot)
{
if(angle == 0 && zoom == LV_IMG_ZOOM_NONE) {
res->x1 = x1;
res->y1 = y1;
res->x2 = x2;
res->y2 = y2;
return;
}
lv_point_t p[4] = {
{x1, y1},
{x2, y1},
{x1, y2},
{x2, y2},
};
lv_point_transform(&p[0], angle, zoom, pivot);
lv_point_transform(&p[1], angle, zoom, pivot);
lv_point_transform(&p[2], angle, zoom, pivot);
lv_point_transform(&p[3], angle, zoom, pivot);
res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x);
res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x);
res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y);
res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y);
}
static inline void ge_blit_set_src(struct ge_bitblt *blt, struct mpp_buf *frame,
int src_crop_x, int src_crop_y,
int src_crop_w, int src_crop_h)
{
/* src buf */
blt->src_buf.buf_type = MPP_PHY_ADDR;
if (frame->format == MPP_FMT_ARGB_8888
|| frame->format == MPP_FMT_RGBA_8888
|| frame->format == MPP_FMT_RGB_888
|| frame->format == MPP_FMT_RGB_565) {
blt->src_buf.phy_addr[0] = frame->phy_addr[0];
blt->src_buf.stride[0] = frame->stride[0];
blt->src_buf.format = frame->format;
} else if (frame->format == MPP_FMT_YUV420P
|| frame->format == MPP_FMT_YUV444P
|| frame->format == MPP_FMT_YUV422P) {
blt->src_buf.phy_addr[0] = frame->phy_addr[0];
blt->src_buf.phy_addr[1] = frame->phy_addr[1];
blt->src_buf.phy_addr[2] = frame->phy_addr[2];
blt->src_buf.stride[0] = frame->stride[0];
blt->src_buf.stride[1] = frame->stride[1];
blt->src_buf.stride[2] = frame->stride[2];
blt->src_buf.format = frame->format;
} else if (frame->format == MPP_FMT_NV12
|| frame->format == MPP_FMT_NV21
|| frame->format == MPP_FMT_NV16
|| frame->format == MPP_FMT_NV61) {
blt->src_buf.phy_addr[0] = frame->phy_addr[0];
blt->src_buf.phy_addr[1] = frame->phy_addr[1];
blt->src_buf.stride[0] = frame->stride[0];
blt->src_buf.stride[1] = frame->stride[1];
blt->src_buf.format = frame->format;
}
blt->src_buf.size.width = frame->size.width;
blt->src_buf.size.height = frame->size.height;
blt->src_buf.crop_en = 1;
blt->src_buf.crop.x = src_crop_x;
blt->src_buf.crop.y = src_crop_y;
blt->src_buf.crop.width = src_crop_w;
blt->src_buf.crop.height = src_crop_h;
blt->src_buf.flags = frame->flags;
}
static inline int ge_blit_run(struct ge_bitblt *blt)
{
int ret;
ret = mpp_ge_bitblt(g_ge, blt);
if (ret < 0) {
LV_LOG_ERROR("bitblt fail");
return LV_RES_INV;
}
ret = mpp_ge_emit(g_ge);
if (ret < 0) {
LV_LOG_ERROR("emit fail");
return LV_RES_INV;
}
ret = mpp_ge_sync(g_ge);
if (ret < 0) {
LV_LOG_ERROR("sync fail");
return LV_RES_INV;
}
return LV_RES_OK;
}
static int ge_run_blit(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t *draw_dsc,
struct mpp_buf *frame, const lv_area_t *clip_area, const lv_area_t *coords)
{
lv_coord_t blend_w;
lv_coord_t blend_h;
int src_crop_x;
int src_crop_y;
int src_crop_w;
int src_crop_h;
int dst_crop_x;
int dst_crop_y;
int dst_crop_w;
int dst_crop_h;
lv_area_t blend_area;
struct ge_bitblt blt = { 0 };
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
int line_length = draw_buf_pitch();
enum mpp_pixel_format fmt = draw_buf_fmt();
if (draw_dsc->zoom == LV_IMG_ZOOM_NONE && draw_dsc->angle == 0) {
if(!_lv_area_intersect(&blend_area, coords, clip_area))
return LV_RES_OK;
blend_w = lv_area_get_width(&blend_area);
blend_h = lv_area_get_height(&blend_area);
src_crop_x = blend_area.x1 - coords->x1;
src_crop_y = blend_area.y1 - coords->y1;
src_crop_w = blend_w;
src_crop_h = blend_h;
dst_crop_x = blend_area.x1 - draw_ctx->buf_area->x1;
dst_crop_y = blend_area.y1 - draw_ctx->buf_area->y1;
dst_crop_w = blend_w;
dst_crop_h = blend_h;
} else {
lv_area_t trans_area;
lv_coord_t src_w = lv_area_get_width(coords);
lv_coord_t src_h = lv_area_get_height(coords);
lv_area_copy(&trans_area, clip_area);
lv_area_move(&trans_area, -coords->x1, -coords->y1);
int32_t xs1_ups, ys1_ups, xs2_ups, ys2_ups;
transform_upscaled(draw_dsc, trans_area.x1, trans_area.y1,
&xs1_ups, &ys1_ups);
transform_upscaled(draw_dsc, trans_area.x2, trans_area.y2,
&xs2_ups, &ys2_ups);
int32_t x1_int = LV_CLAMP(0, LV_MIN(xs1_ups, xs2_ups) >> 8, src_w - 1);
int32_t x2_int = LV_CLAMP(0, LV_MAX(xs1_ups, xs2_ups) >> 8, src_w - 1);
int32_t y1_int = LV_CLAMP(0, LV_MIN(ys1_ups, ys2_ups) >> 8, src_h - 1);
int32_t y2_int = LV_CLAMP(0, LV_MAX(ys1_ups, ys2_ups) >> 8, src_h - 1);
src_crop_x = x1_int;
src_crop_y = y1_int;
src_crop_w = x2_int - x1_int + 1;
src_crop_h = y2_int - y1_int + 1;
lv_area_t out_area;
lv_img_buf_get_transformed_area(&out_area, src_crop_x, src_crop_y,
x2_int, y2_int, draw_dsc->angle,
draw_dsc->zoom, &draw_dsc->pivot);
lv_area_move(&out_area, coords->x1, coords->y1);
dst_crop_x = LV_MAX(out_area.x1, 0);
dst_crop_y = LV_MAX(out_area.y1, 0);
dst_crop_w = lv_area_get_width(&out_area);
dst_crop_h = lv_area_get_height(&out_area);
if (src_crop_w <= 4 || src_crop_h <= 4 ||
dst_crop_w <= 4 || dst_crop_h <= 4) {
LV_LOG_ERROR("invalid size: src w:%d src h:%d, dst w:%d dst h:%d\n",
src_crop_w, src_crop_h,
dst_crop_w, dst_crop_h);
return LV_RES_INV;
}
}
/* src buf */
ge_blit_set_src(&blt, frame, src_crop_x, src_crop_y, src_crop_w, src_crop_h);
/* dst buf */
#ifdef USE_DRAW_BUF
blt.dst_buf.buf_type = MPP_PHY_ADDR;
if (dest_buf == (lv_color_t *)g_draw_buf[0])
blt.dst_buf.phy_addr[0] = (unsigned int)(long)g_draw_buf[0];
else
blt.dst_buf.phy_addr[0] = (unsigned int)(long)g_draw_buf[1];
#else
blt.dst_buf.buf_type = MPP_PHY_ADDR;
if (dest_buf == (lv_color_t *)g_frame_buf[0])
blt.dst_buf.phy_addr[0] = (unsigned int)(long)g_frame_buf[0];
else
blt.dst_buf.phy_addr[0] = (unsigned int)(long)g_frame_buf[1];
#endif
blt.dst_buf.stride[0] = line_length;
blt.dst_buf.size.width = dest_width;
blt.dst_buf.size.height = dest_height;
blt.dst_buf.format = fmt;
blt.dst_buf.crop_en = 1;
blt.dst_buf.crop.x = dst_crop_x;
blt.dst_buf.crop.y = dst_crop_y;
blt.dst_buf.crop.width = dst_crop_w;
blt.dst_buf.crop.height = dst_crop_h;
if (!is_rgb(blt.src_buf.format) &&
(blt.src_buf.crop.width < 8 || blt.src_buf.crop.height < 8)) {
//rt_kprintf("invalid src size, the min size of yuv is 8x8\n");
return LV_RES_INV;
}
if (!is_rgb(blt.dst_buf.format) &&
(blt.dst_buf.crop.width < 8 || blt.dst_buf.crop.height < 8)) {
//rt_kprintf("invalid dst size, the min size of yuv is 8x8\n");
return LV_RES_INV;
}
/* ctrl */
blt.ctrl.flags = draw_dsc->angle / 900;
if(draw_dsc->opa >= LV_OPA_MAX && frame->format != MPP_FMT_ARGB_8888)
blt.ctrl.alpha_en = 0;
else
blt.ctrl.alpha_en = 1;
blt.ctrl.src_alpha_mode = 2;
blt.ctrl.src_global_alpha = draw_dsc->opa;
#ifdef AIC_GE_DITHER
if (AICFB_FORMAT == MPP_FMT_RGB_565 && draw_dsc->zoom == 256) {
blt.ctrl.dither_en = 1;
if (blt.ctrl.alpha_en || blt.src_buf.format == MPP_FMT_RGB_565)
blt.ctrl.dither_en = 0;
}
#endif
aicos_dcache_clean_invalid_range((ulong *)dest_buf, (ulong)ALIGN_UP(draw_buf_len(), CACHE_LINE_SIZE));
if (ge_blit_run(&blt) == LV_RES_INV)
return LV_RES_INV;
return LV_RES_OK;
}
static int get_bpp_by_fmt(enum mpp_pixel_format fmt)
{
if (fmt == MPP_FMT_ARGB_8888)
return 4;
else if (fmt == MPP_FMT_RGB_888)
return 3;
else if (fmt == MPP_FMT_RGB_565)
return 2;
return 4;
}
static int ge_run_rotate(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t *draw_dsc,
struct mpp_buf *frame, const lv_area_t *blend_area, const lv_area_t *coords)
{
int ret;
struct ge_rotation rot = { 0 };
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
lv_coord_t blend_width = lv_area_get_width(blend_area);
lv_coord_t blend_height = lv_area_get_height(blend_area);
int line_length = draw_buf_pitch();
enum mpp_pixel_format fmt = draw_buf_fmt();
int32_t zoom = 256;
int out_w = 0;
int out_h = 0;
int out_stride = 0;
int out_size = 0;
u32 out_addr = 0;
u32 out_addr_align = 0;
int out_pivot_x = 0;
int out_pivot_y = 0;
/* src buf */
rot.src_buf.buf_type = MPP_PHY_ADDR;
if (frame->format == MPP_FMT_ARGB_8888
|| frame->format == MPP_FMT_RGBA_8888
|| frame->format == MPP_FMT_RGB_888
|| frame->format == MPP_FMT_RGB_565) {
if (draw_dsc->zoom == LV_IMG_ZOOM_NONE) {
rot.src_buf.phy_addr[0] = frame->phy_addr[0];
rot.src_buf.stride[0] = frame->stride[0];
rot.src_buf.format = frame->format;
rot.src_buf.size.width = frame->size.width;
rot.src_buf.size.height = frame->size.height;
rot.src_rot_center.x = draw_dsc->pivot.x;
rot.src_rot_center.y = draw_dsc->pivot.y;
} else {
struct ge_bitblt blt = { 0 };
int bpp = get_bpp_by_fmt(frame->format);
zoom = draw_dsc->zoom;
out_w = (frame->size.width * zoom) >> 8;
out_h = (frame->size.height * zoom) >> 8;
out_pivot_x = (draw_dsc->pivot.x * zoom) >> 8;
out_pivot_y = (draw_dsc->pivot.y * zoom) >> 8;
out_stride = ALIGN_UP(out_w * bpp, 8);
out_size = out_stride * out_h;
out_addr = (u32)(ulong)aicos_malloc_try_cma(out_size + 1023 + CACHE_LINE_SIZE);
if (out_addr == 0) {
LV_LOG_ERROR("malloc fail\n");
goto failed;
}
out_addr_align = ALIGN_1024B(out_addr);
aicos_dcache_clean_invalid_range((ulong *)((ulong)out_addr_align), ALIGN_UP(out_size, CACHE_LINE_SIZE));
/* src buf */
blt.src_buf.buf_type = MPP_PHY_ADDR;
blt.src_buf.phy_addr[0] = frame->phy_addr[0];
blt.src_buf.stride[0] = frame->stride[0];
blt.src_buf.format = frame->format;
blt.src_buf.size.width = frame->size.width;
blt.src_buf.size.height = frame->size.height;
/* dst buf */
blt.dst_buf.buf_type = MPP_PHY_ADDR;
blt.dst_buf.phy_addr[0] = out_addr_align;
blt.dst_buf.stride[0] = out_stride;
blt.dst_buf.format = frame->format;
blt.dst_buf.size.width = out_w;
blt.dst_buf.size.height = out_h;
ret = mpp_ge_bitblt(g_ge, &blt);
if (ret < 0) {
LV_LOG_ERROR("bitblt fail\n");
goto failed;
}
ret = mpp_ge_emit(g_ge);
if (ret < 0) {
LV_LOG_ERROR("emit fail\n");
goto failed;
}
ret = mpp_ge_sync(g_ge);
if (ret < 0) {
LV_LOG_ERROR("sync fail\n");
goto failed;
}
rot.src_buf.phy_addr[0] = out_addr_align;
rot.src_buf.stride[0] = out_stride;
rot.src_buf.format = frame->format;
rot.src_buf.size.width = out_w;
rot.src_buf.size.height = out_h;
rot.src_rot_center.x = out_pivot_x;
rot.src_rot_center.y = out_pivot_y;
}
} else {
LV_LOG_ERROR("frame unsupport format:%d\n", frame->format);
return LV_RES_INV;
}
/* dst buf */
#ifdef USE_DRAW_BUF
rot.dst_buf.buf_type = MPP_PHY_ADDR;
if (dest_buf == (lv_color_t *)g_draw_buf[0])
rot.dst_buf.phy_addr[0] = (unsigned int)(long)g_draw_buf[0];
else
rot.dst_buf.phy_addr[0] = (unsigned int)(long)g_draw_buf[1];
#else
rot.dst_buf.buf_type = MPP_PHY_ADDR;
if (dest_buf == (lv_color_t *)g_frame_buf[0])
rot.dst_buf.phy_addr[0] = (unsigned int)(long)g_frame_buf[0];
else
rot.dst_buf.phy_addr[0] = (unsigned int)(long)g_frame_buf[1];
#endif
rot.dst_buf.stride[0] = line_length;
rot.dst_buf.size.width = dest_width;
rot.dst_buf.size.height = dest_height;
rot.dst_buf.format = fmt;
rot.dst_buf.crop_en = 1;
rot.dst_buf.crop.x = blend_area->x1;
rot.dst_buf.crop.y = blend_area->y1;
rot.dst_buf.crop.width = blend_width;
rot.dst_buf.crop.height = blend_height;
rot.dst_rot_center.x = coords->x1 + draw_dsc->pivot.x - blend_area->x1;
rot.dst_rot_center.y = coords->y1 + draw_dsc->pivot.y - blend_area->y1;
/* angle */
rot.angle_sin = SIN((double)draw_dsc->angle / 10) * 4096;
rot.angle_cos = COS((double)draw_dsc->angle / 10) * 4096;
/* ctrl */
rot.ctrl.flags = 0;
rot.ctrl.alpha_en = 1;
rot.ctrl.src_alpha_mode = 2;
rot.ctrl.src_global_alpha = draw_dsc->opa;
if (rot.dst_buf.crop.width < 4 || rot.dst_buf.crop.height < 4) {
goto failed;
}
aicos_dcache_clean_invalid_range((ulong *)dest_buf, (ulong)ALIGN_UP(draw_buf_len(), CACHE_LINE_SIZE));
ret = mpp_ge_rotate(g_ge, &rot);
if (ret < 0) {
LV_LOG_WARN("rotate fail\n");
goto failed;
}
ret = mpp_ge_emit(g_ge);
if (ret < 0) {
LV_LOG_WARN("emit fail\n");
goto failed;
}
ret = mpp_ge_sync(g_ge);
if (ret < 0) {
LV_LOG_WARN("sync fail\n");
goto failed;
}
if (out_addr)
aicos_free(MEM_CMA, (void*)(unsigned long)out_addr);
return LV_RES_OK;
failed:
if (out_addr)
aicos_free(MEM_CMA, (void*)(unsigned long)out_addr);
return LV_RES_INV;
}
static int ge_run_fill(lv_draw_ctx_t * draw_ctx, unsigned int color, unsigned char opa,
int blend_enable, const lv_area_t *blend_area)
{
int ret;
struct ge_fillrect fill = { 0 };
lv_color_t * dest_buf = draw_ctx->buf;
lv_coord_t dest_width = lv_area_get_width(draw_ctx->buf_area);
lv_coord_t dest_height = lv_area_get_height(draw_ctx->buf_area);
lv_coord_t blend_width = lv_area_get_width(blend_area);
lv_coord_t blend_height = lv_area_get_height(blend_area);
int bpp = draw_buf_bpp();
int line_length = draw_buf_pitch();
enum mpp_pixel_format fmt = draw_buf_fmt();
if (bpp == 16) {
rgb565_to_argb((unsigned short)color, &color);
}
/* fill info */
fill.type = GE_NO_GRADIENT;
fill.start_color = color;
fill.end_color = 0;
/* dst buf */
#ifdef USE_DRAW_BUF
fill.dst_buf.buf_type = MPP_PHY_ADDR;
if (dest_buf == (lv_color_t *)g_draw_buf[0])
fill.dst_buf.phy_addr[0] = (unsigned int)(long)g_draw_buf[0];
else
fill.dst_buf.phy_addr[0] = (unsigned int)(long)g_draw_buf[1];
#else
fill.dst_buf.buf_type = MPP_PHY_ADDR;
if (dest_buf == (lv_color_t *)g_frame_buf[0])
fill.dst_buf.phy_addr[0] = (unsigned int)(long)g_frame_buf[0];
else
fill.dst_buf.phy_addr[0] = (unsigned int)(long)g_frame_buf[1];
#endif
fill.dst_buf.stride[0] = line_length;
fill.dst_buf.size.width = dest_width;
fill.dst_buf.size.height = dest_height;
fill.dst_buf.format = fmt;
fill.dst_buf.crop_en = 1;
fill.dst_buf.crop.x = blend_area->x1;
fill.dst_buf.crop.y = blend_area->y1;
fill.dst_buf.crop.width = blend_width;
fill.dst_buf.crop.height = blend_height;
/* ctrl */
fill.ctrl.flags = 0;
if(opa < LV_OPA_MAX && blend_enable)
fill.ctrl.alpha_en = 1;
else
fill.ctrl.alpha_en = 0;
fill.ctrl.src_alpha_mode = 1;
fill.ctrl.src_global_alpha = opa;
aicos_dcache_clean_invalid_range((ulong *)dest_buf, (ulong)ALIGN_UP(draw_buf_len(), CACHE_LINE_SIZE));
ret = mpp_ge_fillrect(g_ge, &fill);
if (ret < 0) {
LV_LOG_WARN("fillrect1 fail\n");
return LV_RES_INV;
}
ret = mpp_ge_emit(g_ge);
if (ret < 0) {
LV_LOG_WARN("emit fail\n");
return LV_RES_INV;
}
ret = mpp_ge_sync(g_ge);
if (ret < 0) {
LV_LOG_WARN("sync fail\n");
return LV_RES_INV;
}
return LV_RES_OK;
}
bool is_fix_angle(int angle) {
if (angle == 0 || angle == 900 || angle == 1800 || angle == 2700)
return true;
else
return false;
}
static lv_res_t hw_decode(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t *draw_dsc,
const void *src, const lv_area_t *blend_area, const lv_area_t *coords)
{
struct decode_config config = { 0 };
int ret;
struct mpp_decoder* dec;
struct mpp_frame frame;
img_info *info;
int type;
int lv_ret = LV_RES_OK;
info = img_info_init(src);
if(!info) return LV_RES_INV;
type = info->type ?
MPP_CODEC_VIDEO_DECODER_PNG:MPP_CODEC_VIDEO_DECODER_MJPEG;
config.bitstream_buffer_size = (info->img_size + 1023) & (~1023);
config.extra_frame_num = 0;
config.packet_count = 1;
if(type == MPP_CODEC_VIDEO_DECODER_MJPEG)
config.pix_fmt = MPP_FMT_YUV420P;
else if(type == MPP_CODEC_VIDEO_DECODER_PNG)
config.pix_fmt = MPP_FMT_ARGB_8888;
dec = mpp_decoder_create(type);
if (!dec) {
lv_ret = LV_RES_INV;
LV_LOG_ERROR("mpp_decoder_create failed\n");
goto free_img;
}
mpp_decoder_init(dec, &config);
struct mpp_packet packet;
mpp_decoder_get_packet(dec, &packet, info->img_size);
uint32_t len = 0;
lv_fs_read(&(info->fp), packet.data, info->img_size, &len);
packet.size = info->img_size;
packet.flag = PACKET_FLAG_EOS;
mpp_decoder_put_packet(dec, &packet);
mpp_decoder_decode(dec);
ret = mpp_decoder_get_frame(dec, &frame);
if (ret < 0) {
lv_ret = LV_RES_INV;
LV_LOG_ERROR("mpp decoder get frame failed:%d\n", ret);
goto free_dec;
}
if (is_fix_angle(draw_dsc->angle))
lv_ret = ge_run_blit(draw_ctx, draw_dsc, &frame.buf, blend_area, coords);
else if (draw_dsc->angle > 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE)
lv_ret = ge_run_rotate(draw_ctx, draw_dsc, &frame.buf, blend_area, coords);
else
lv_ret = LV_RES_INV;
mpp_decoder_put_frame(dec, &frame);
free_dec:
mpp_decoder_destory(dec);
free_img:
img_info_deinit(info);
return lv_ret;
}
lv_res_t lv_draw_aic_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const void *src)
{
/*Use the clip area as draw area*/
lv_area_t draw_area;
bool fake_image = false;
char* ptr = NULL;
if (lv_img_src_get_type(src) == LV_IMG_SRC_FILE) {
ptr = strrchr(src, '.');
if (!strcmp(ptr, ".fake"))
fake_image = true;
else
return LV_RES_INV;
} else {
return LV_RES_INV;
}
lv_area_copy(&draw_area, draw_ctx->clip_area);
bool mask_any = lv_draw_mask_is_any(&draw_area);
bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
lv_area_t b_area;
lv_draw_sw_blend_dsc_t blend_dsc;
lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t));
blend_dsc.opa = draw_dsc->opa;
blend_dsc.blend_mode = draw_dsc->blend_mode;
blend_dsc.blend_area = &b_area;
if (!mask_any && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
blend_dsc.src_buf = NULL;
blend_dsc.blend_area = coords;
lv_area_t blend_area;
if (!transform) {
//lv_area_copy(&blend_area, coords);
if (!_lv_area_intersect(&blend_area, blend_dsc.blend_area, draw_ctx->clip_area)) {
return LV_RES_INV;
}
} else {
lv_area_copy(&blend_area, draw_ctx->clip_area);
}
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
lv_color_t * dest_buf = draw_ctx->buf;
if (blend_dsc.mask_buf == NULL && blend_dsc.blend_mode == LV_BLEND_MODE_NORMAL
&& (dest_buf == disp->driver->draw_buf->buf1 || dest_buf == disp->driver->draw_buf->buf2)
&& disp->driver->set_px_cb == NULL ) {
if (fake_image) {
int width;
int height;
int blend;
unsigned int color;
FAKE_IMAGE_PARSE((char *)src, &width, &height, &blend, &color);
return ge_run_fill(draw_ctx, color, (color >> 24) & 0xff, blend, &blend_area);
} else {
return hw_decode(draw_ctx, draw_dsc, src, &blend_area, coords);
}
} else {
LV_LOG_USER("lv res inv\n");
return LV_RES_INV;
}
}
return LV_RES_OK;
}
LV_ATTRIBUTE_FAST_MEM void lv_draw_aic_sw_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const uint8_t *src_buf, lv_img_cf_t cf)
{
struct mpp_frame frame;
memcpy(&frame, src_buf, sizeof(frame));
if (frame.buf.format == MPP_FMT_ARGB_8888) {
cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
} else if (frame.buf.format == MPP_FMT_RGB_565) {
cf = LV_IMG_CF_TRUE_COLOR;
} else {
LV_LOG_ERROR("unsupported format:%d\n", frame.buf.format);
return;
}
#if LV_COLOR_DEPTH == 16
if (cf == LV_IMG_CF_TRUE_COLOR_ALPHA)
cf = LV_IMG_CF_RESERVED_15;
#endif
#if LV_SUPPORT_SET_IMAGE_STRIDE
draw_ctx->src_stride = (int)frame.buf.stride[0];
#endif
lv_draw_sw_img_decoded(draw_ctx, draw_dsc, coords, (void *)(long)frame.buf.phy_addr[0], cf);
#if LV_SUPPORT_SET_IMAGE_STRIDE
draw_ctx->src_stride = 0;
#endif
}
LV_ATTRIBUTE_FAST_MEM void lv_draw_aic_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords, const uint8_t *src_buf, lv_img_cf_t cf)
{
lv_area_t draw_area;
bool mask_any;
lv_area_t b_area;
lv_draw_sw_blend_dsc_t blend_dsc;
if (cf != LV_IMG_CF_RESERVED_16) {
lv_draw_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
return;
}
lv_area_copy(&draw_area, draw_ctx->clip_area);
mask_any = lv_draw_mask_is_any(&draw_area);
lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t));
blend_dsc.opa = draw_dsc->opa;
blend_dsc.blend_mode = draw_dsc->blend_mode;
blend_dsc.blend_area = &b_area;
if (!mask_any && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
blend_dsc.src_buf = NULL;
blend_dsc.blend_area = coords;
lv_area_t blend_area;
lv_area_copy(&blend_area, draw_ctx->clip_area);
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
lv_color_t * dest_buf = draw_ctx->buf;
if (blend_dsc.mask_buf == NULL && blend_dsc.blend_mode == LV_BLEND_MODE_NORMAL
&& (dest_buf == disp->driver->draw_buf->buf1 || dest_buf == disp->driver->draw_buf->buf2)
&& disp->driver->set_px_cb == NULL ) {
struct mpp_buf frame;
memcpy(&frame, src_buf, sizeof(frame));
if (!is_fix_angle(draw_dsc->angle)) {
ge_run_rotate(draw_ctx, draw_dsc, &frame, &blend_area, coords);
} else {
if (draw_dsc->antialias && draw_dsc->angle != 0) {
if (frame.format >= MPP_FMT_YUV420P)
ge_run_blit(draw_ctx, draw_dsc, &frame, &blend_area, coords);
else
ge_run_rotate(draw_ctx, draw_dsc, &frame, &blend_area, coords);
} else {
ge_run_blit(draw_ctx, draw_dsc, &frame, &blend_area, coords);
}
}
} else {
lv_draw_aic_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
}
} else {
lv_draw_aic_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
}
return;
}
void lv_draw_aic_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc)
{
lv_area_t blend_area;
bool done = false;
if (dsc->mask_buf && dsc->mask_res == LV_DRAW_MASK_RES_TRANSP)
return;
/*Let's get the blend area which is the intersection of the area to fill and the clip area.*/
if (!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area))
return; /*Fully clipped, nothing to do */
/*Make the blend area relative to the buffer*/
lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
lv_color_t * dest_buf = draw_ctx->buf;
if (dsc->mask_buf == NULL && dsc->blend_mode == LV_BLEND_MODE_NORMAL
&& (dest_buf == disp->driver->draw_buf->buf1 || dest_buf == disp->driver->draw_buf->buf2)
&& disp->driver->set_px_cb == NULL ) {
int ret = LV_RES_INV;
unsigned int color = dsc->color.full;
unsigned char opa = dsc->opa;
if (!dsc->src_buf)
ret = ge_run_fill(draw_ctx, color, opa, 1, &blend_area);
if (ret == LV_RES_OK)
done = true;
}
if (!done)
lv_draw_sw_blend_basic(draw_ctx, dsc);
}