nt9856x/code/application/source/cardv/SrcCode/lv_drivers/display/fbdev.c
2023-03-28 15:07:53 +08:00

987 lines
24 KiB
C
Executable File

/**
* @file fbdev.c
*
*/
/*********************
* INCLUDES
*********************/
#include "fbdev.h"
#include "hd_gfx.h"
#include "vendor_gfx.h"
#include "hd_common.h"
#include <kwrap/perf.h>
#include <kwrap/util.h>
#if defined(_UI_STYLE_LVGL_)
#include "PrjInc.h"
#endif
#if USE_FBDEV || USE_BSD_FBDEV
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <fcntl.h>
#if !defined(__FREERTOS)
#include <sys/mman.h>
#include <sys/ioctl.h>
#endif
#if USE_BSD_FBDEV
#include <sys/fcntl.h>
#include <sys/time.h>
#include <sys/consio.h>
#include <sys/fbio.h>
#else /* USE_BSD_FBDEV */
#if !defined(__FREERTOS)
#include <linux/fb.h>
#endif
#endif /* USE_BSD_FBDEV */
/*********************
* DEFINES
*********************/
#ifndef FBDEV_PATH
#define FBDEV_PATH "/dev/fb0"
#endif
//#define FBDEV_DBG
#ifdef FBDEV_DBG
#define fbdev_msg printf
#else
#define fbdev_msg(...)
#endif
//#define FBDEV_PERF
#ifdef FBDEV_PERF
#define fbdev_perf printf
#else
#define fbdev_perf(...)
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STRUCTURES
**********************/
#if (USE_BSD_FBDEV || defined(__FREERTOS))
struct bsd_fb_var_info{
int32_t xoffset;
int32_t yoffset;
int32_t xres;
int32_t yres;
int bits_per_pixel;
};
struct bsd_fb_fix_info{
long int line_length;
long int smem_len;
};
#endif
/**********************
* Function Declaration
**********************/
HD_RESULT LVGL_rotate_fb(UINT32 dst_pa, UINT32 src_pa,lv_disp_drv_t * disp_drv,UINT32 fmt);
/**********************
* STATIC VARIABLES
**********************/
#if USE_BSD_FBDEV
static struct bsd_fb_var_info vinfo;
static struct bsd_fb_fix_info finfo;
#else
#if !defined(__FREERTOS)
static struct fb_var_screeninfo vinfo;
static struct fb_fix_screeninfo finfo;
#else
#include "sys_mempool.h"
#include "vendor_videoout.h"
static struct bsd_fb_var_info vinfo;
//static struct bsd_fb_fix_info finfo;
#define FBIOPAN_DISPLAY (0x1)
#endif
#endif /* USE_BSD_FBDEV */
#if LV_COLOR_DEPTH == 24
HD_RESULT disp_gfx_copy_8565(UINT32 dst_pa, UINT32 src_pa,lv_disp_drv_t * disp_drv);
HD_RESULT disp_gfx_rotate_8565(UINT32 dst_pa, UINT32 src_pa,lv_disp_drv_t * disp_drv);
void lv_gpu_nvt_dma2d_rotate_8565(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir);
#endif
void lv_gpu_nvt_dma2d_rotate(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir, bool flush);
char *fbp = 0;
long int screensize = 0;
static UINT32 buf1_pa;
#if LV_USE_GPU_NVT_DMA2D
#include "lvgl/src/lv_gpu/lv_gpu_nvt_dma2d.h"
static UINT32 hdal_fmt=DISPLAY_HDAL_OSD_FMT; //for gfx need hdal fmt
#endif
static int fbfd = 0;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/*********************************************
* IMPORTANT!
*
* Do not edit lv_user_rounder_callback
*
*********************************************/
void lv_user_rounder_callback(
lv_disp_drv_t* disp_drv,
lv_area_t* area)
{
#if LV_USE_GPU_NVT_DMA2D == 1
#if LV_COLOR_DEPTH != 8
#if LV_USER_CFG_USE_ROTATE_BUFFER
uint8_t alignment = 16;
#else
uint8_t alignment = 4;
#endif
area->x1 = ALIGN_FLOOR(area->x1, alignment);
area->y1 = ALIGN_FLOOR(area->y1, alignment);
lv_coord_t copy_w = (area->x2 - area->x1) + 1;
lv_coord_t copy_h = (area->y2 - area->y1) + 1;
uint8_t remainder_copy_w = copy_w % alignment;
uint8_t remainder_copy_h = copy_h % alignment;
if(area->x1 == area->x2){
area->x2 += (alignment - 1);
}
else if(remainder_copy_w){
area->x2 += (alignment - remainder_copy_w);
}
if( (area->y1 == area->y2)){
area->y2 += (alignment - 1);
}
else if(remainder_copy_h){
area->y2 += (alignment - remainder_copy_h);
}
/* check out of area, LV_MAX_RES_HOR & LV_MAX_RES_VER should be aligned too. */
if(area->x2 > (disp_drv->hor_res - 1))
area->x2 = disp_drv->hor_res - 1;
if(area->y2 > (disp_drv->ver_res - 1))
area->y2 = disp_drv->ver_res - 1;
#else
/*******************************************************************
* invalidate area update still has issues for LV_COLOR_DEPTH = 8,
* keep fully update.
******************************************************************/
area->x1 = 0;
area->y1 = 0;
area->x2 = disp_drv->hor_res - 1;
area->y2 = disp_drv->ver_res - 1;
#endif
#endif
}
/**
* Flush a buffer to the marked area
* @param x1 left coordinate
* @param y1 top coordinate
* @param x2 right coordinate
* @param y2 bottom coordinate
* @param color_p an array of colors
*/
void fbdev_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p)
{
if(fbp == NULL) return;
fbdev_msg("fbdev_flush : %d,%d,%d,%d {%lu, %lu, %lu, %lu}\r\n",x1,y1,x2,y2, vinfo.xres, vinfo.xoffset, vinfo.yres, vinfo.yoffset);
/*Return if the area is out the screen*/
if(x2 < 0) return;
if(y2 < 0) return;
if(x1 > (int32_t)(vinfo.xres) - 1) return;
if(y1 > (int32_t)(vinfo.yres) - 1) return;
/*Truncate the area to the screen*/
int32_t act_x1 = x1 < 0 ? 0 : x1;
int32_t act_y1 = y1 < 0 ? 0 : y1;
int32_t act_x2 = x2 > (int32_t)(vinfo.xres) - 1 ? (int32_t)(vinfo.xres) - 1 : x2;
int32_t act_y2 = y2 > (int32_t)(vinfo.yres) - 1 ? (int32_t)(vinfo.yres) - 1 : y2;
long int location = 0;
/*32 or 24 bit per pixel*/
if(vinfo.bits_per_pixel == 32) {
uint32_t *fbp32 = (uint32_t*)fbp;
for(int32_t y = act_y1; y <= act_y2; y++) {
for(int32_t x = act_x1; x <= act_x2; x++) {
location = x + y * vinfo.xres;
fbp32[location] = lv_color_to32(*color_p);
color_p++;
}
color_p += x2 - act_x2;
}
}
/*16 bit per pixel*/
else if(vinfo.bits_per_pixel == 16) {
uint16_t *fbp16 = (uint16_t*)fbp;
for(int32_t y = act_y1; y <= act_y2; y++) {
for(int32_t x = act_x1; x <= act_x2; x++) {
location = x + y * vinfo.xres;
fbp16[location] = color_p->full;
color_p++;
}
color_p += x2 - act_x2;
}
}
/**********************************************************************************
* 24 bit per pixel
*
* IMPORTANT!!
*
* set_px_cb is set in LV_COLOR_DEPTH = 24, color_p is already a two plane buffer,
* do not get pixel data by accessing member of lv_color_t
* **********************************************************************************/
else if(vinfo.bits_per_pixel == 24) {
/* RGB plane*/
uint16_t *fbp16 = (uint16_t*)fbp;
uint16_t *color_p16 = (uint16_t*)color_p;
/* Alpha plane, 565 = 2 bytes, shift to alpha address */
uint8_t *fbp8 = (uint8_t*)fbp;
uint8_t *color_p8 = (uint8_t*)color_p;
fbp8 += (vinfo.yres * vinfo.xres * sizeof(color_p->full));
color_p8 += (vinfo.yres * vinfo.xres * sizeof(color_p->full));
for(int32_t y = act_y1 ; y <= act_y2 ; y++)
{
for( int32_t x = act_x1 ; x <= act_x2 ; x++)
{
location = x + y * vinfo.xres;
fbp16[location] = color_p16[location];
fbp8[location] = color_p8[location];
}
}
}
/*8 bit per pixel*/
else if(vinfo.bits_per_pixel == 8) {
uint8_t *fbp8 = (uint8_t*)fbp;
for(int32_t y = act_y1 ; y <= act_y2 ; y++)
{
for(int32_t x = act_x1 ; x <= act_x2 ; x++)
{
location = x + y * vinfo.xres;
fbp8[location] = color_p->full;
color_p++;
}
color_p += x2 - act_x2;
}
} else {
LV_LOG_ERROR("current vinfo.bits_per_pixel(%d) is not supported!", vinfo.bits_per_pixel);
}
}
#if !defined(__FREERTOS)
void fbdev_init(void)
{
// Open the file for reading and writing
int count =1000;
HD_COMMON_MEM_VIRT_INFO vir_meminfo = {0};
int ERcode;
while(count){
fbfd = open(FBDEV_PATH, O_RDWR);
if (fbfd<0) {
usleep(10);
count--;
} else {
break;
}
}
if(fbfd == -1) {
perror("Error: cannot open framebuffer device");
return;
}
fbdev_msg("The framebuffer device was opened successfully.~~~~\n");
// Get fixed screen information
if(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("Error reading fixed information");
return;
}
// Get variable screen information
if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("Error reading variable information");
return;
}
vinfo.xres_virtual = vinfo.xres;
#if LV_USER_CFG_USE_TWO_BUFFER
vinfo.yres_virtual = vinfo.yres * 2;
#else
vinfo.yres_virtual = vinfo.yres;
#endif
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo) == -1) {
perror("Could not set variable screen info!\n");
return;
}
fbdev_msg("The mem is :%d\n",finfo.smem_len);
fbdev_msg("The line_length is :%d\n",finfo.line_length);
fbdev_msg("The xres is :%d\n",vinfo.xres);
fbdev_msg("The yres is :%d\n",vinfo.yres);
fbdev_msg("bits_per_pixel is :%d\n",vinfo.bits_per_pixel);
fbdev_msg("The yres_virtual is :%d\n",vinfo.yres_virtual);
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
fbdev_msg("screen size = %u xres = %u yres = %u bpp = %u\r\n", screensize, vinfo.xres , vinfo.yres , vinfo.bits_per_pixel);
// Map the device to memory
fbp = (char *)mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if((intptr_t)fbp == -1) {
perror("Error: failed to map framebuffer device to memory");
return;
}
memset(fbp, 0, screensize);
fbdev_msg("The framebuffer device was mapped to memory successfully.\n");
vir_meminfo.va = (void *)(fbp);
ERcode = hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo);
if ( ERcode != HD_OK) {
fbdev_msg("_DC_bltDestOffset map fail %d\n",ERcode);
return;
}
buf1_pa = vir_meminfo.pa;
}
void fbdev_exit(void)
{
close(fbfd);
}
#else // __FREERTOS
#define ioctl fbdev_ioctl
int fbdev_ioctl(int f, unsigned int cmd, void *arg)
{
int ret = 0;
switch(cmd){
case FBIOPAN_DISPLAY :
{
VENDOR_FB_INIT fb_init;
struct bsd_fb_var_info *my_vinfo =arg;
//assign bf buffer to FB_INIT
fb_init.fb_id = HD_FB0;
fb_init.pa_addr = (int) fbp + (my_vinfo->xres * my_vinfo->yoffset * (my_vinfo->bits_per_pixel / 8));
fb_init.buf_len = (my_vinfo->xres * my_vinfo->yres * (my_vinfo->bits_per_pixel / 8));
fbdev_msg("pa_addr 0x%x buf_len 0x%x \r\n",fb_init.pa_addr,fb_init.buf_len);
ret = vendor_videoout_set(VENDOR_VIDEOOUT_ID0, VENDOR_VIDEOOUT_ITEM_FB_INIT, &fb_init);
return ret;
};
break;
default :
printf("unsupport cmd = %d\r\n", cmd);
break;
};
return ret;
}
void fbdev_init(void)
{
screensize = OSD_SCREEN_SIZE;
fbp = (char *)mempool_disp_osd1_pa;
buf1_pa = mempool_disp_osd1_pa;
memset(fbp,0,POOL_SIZE_OSD);
memset((void *)&vinfo,0,sizeof(struct bsd_fb_var_info));
vinfo.xoffset = 0;
vinfo.yoffset = 0;
vinfo.xres = DISPLAY_OSD_W;
vinfo.yres = DISPLAY_OSD_H;
vinfo.bits_per_pixel = LV_COLOR_DEPTH;
fbfd =1;
fbdev_msg("The xres is :%d\n",vinfo.xres);
fbdev_msg("The yres is :%d\n",vinfo.yres);
fbdev_msg("bits_per_pixel is :%d\n",vinfo.bits_per_pixel);
}
void fbdev_exit(void)
{
fbfd =0;
}
#endif
#include "kwrap/debug.h"
#if LV_USE_GPU_NVT_DMA2D
static UINT32 disp_get_dst_va(lv_disp_drv_t * disp_drv)
{
UINT32 dst_va;
#if LV_USER_CFG_USE_TWO_BUFFER
if(vinfo.yoffset == 0){
dst_va = (UINT32)fbp + screensize;
}
else{
dst_va = (UINT32)fbp;
}
#else
dst_va = (UINT32)fbp;
#endif
return dst_va;
}
static void disp_set_pan_display(lv_disp_drv_t * disp_drv)
{
#if LV_USER_CFG_USE_TWO_BUFFER
UINT32 fpb_scr, fpb_dst;
const lv_area_t area = {0, 0, disp_drv->hor_res - 1, disp_drv->ver_res - 1};
/* check is last chunk */
if(disp_drv->buffer->flushing_last){
if(vinfo.yoffset == 0){
vinfo.yoffset = vinfo.yres;
fpb_scr = (UINT32)fbp + screensize;
fpb_dst = (UINT32)fbp;
}
else{
vinfo.yoffset = 0;
fpb_scr = (UINT32)fbp;
fpb_dst = (UINT32)fbp + screensize;
}
if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {
fbdev_msg("Error to do pan display. %s\n",strerror(errno));
}
lv_gpu_nvt_dma2d_copy(
(lv_color_t *) fpb_scr,
disp_drv->hor_res,
disp_drv->ver_res,
(lv_color_t *) fpb_dst,
disp_drv->hor_res,
disp_drv->ver_res,
&area,
true
);
}
#endif
}
/* Flush the content of the internal buffer the specific area on the display
* You can use DMA or any hardware acceleration to do this operation in the background but
* 'lv_disp_flush_ready()' has to be called when finished. */
#if (LV_COLOR_DEPTH == 24)
#if LV_USER_CFG_USE_ROTATE_BUFFER
void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
UINT32 dst_va = disp_get_dst_va(disp_drv);
lv_gpu_nvt_dma2d_rotate_8565(
(lv_color_t *)dst_va, disp_drv->hor_res,
(lv_color_t *)color_p, disp_drv->hor_res,
*area, VDO_ROTATE_DIR);
disp_set_pan_display(disp_drv);
lv_disp_flush_ready(disp_drv);
}
#else
void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
UINT32 dst_va = disp_get_dst_va(disp_drv);
#if 1
lv_gpu_nvt_dma2d_copy(
color_p,
disp_drv->hor_res,
disp_drv->ver_res,
(lv_color_t *)dst_va,
disp_drv->hor_res,
disp_drv->ver_res,
area,
true
);
#else /* CPU flush for debugging */
uint32_t location, location2;
const uint32_t alpha_offset = LV_HOR_RES_MAX * LV_VER_RES_MAX * 2;
for(int i=area->x1 ; i<=area->x2 ; i++)
{
for(int j=area->y1 ; j<=area->y2 ; j++)
{
location = i + j * disp_drv->hor_res;
location2 = (i-area->x1) + (j-area->y1) * disp_drv->hor_res;
*(((uint16_t*)dst_va) + location ) = *((uint16_t*)(vir_meminfo.va) + location2);
*((uint8_t*)(dst_va + alpha_offset + location)) = *((uint8_t*)(vir_meminfo.va) + location2 + alpha_offset);
}
}
hd_common_mem_flush_cache(color_p, disp_drv->hor_res * disp_drv->ver_res * sizeof(lv_color_t));
#endif
disp_set_pan_display(disp_drv);
lv_disp_flush_ready(disp_drv);
}
#endif
#else /* 32 & 8 */
#if LV_USER_CFG_USE_ROTATE_BUFFER
void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
UINT32 dst_va = disp_get_dst_va(disp_drv);
lv_gpu_nvt_dma2d_rotate(
(lv_color_t *)dst_va, disp_drv->hor_res,
(lv_color_t *)color_p, disp_drv->hor_res,
*area, VDO_ROTATE_DIR, true);
disp_set_pan_display(disp_drv);
lv_disp_flush_ready(disp_drv);
}
#else
void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
UINT32 dst_va = disp_get_dst_va(disp_drv);
lv_gpu_nvt_dma2d_copy(
color_p,
lv_area_get_width(area),
lv_area_get_height(area),
(lv_color_t *)dst_va,
disp_drv->hor_res,
disp_drv->ver_res,
area,
true
);
disp_set_pan_display(disp_drv);
lv_disp_flush_ready(disp_drv);
}
#endif
#endif
#else
/* Flush the content of the internal buffer the specific area on the display
* You can use DMA or any hardware acceleration to do this operation in the background but
* 'lv_disp_flush_ready()' has to be called when finished. */
void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
fbdev_flush(area->x1,area->y1,area->x2,area->y2,color_p);
lv_disp_flush_ready(disp_drv);
}
#endif
#if LV_USE_GPU_NVT_DMA2D
#if LV_COLOR_DEPTH == 24
void set_px_cb_8565(
struct _disp_drv_t * disp_drv,
uint8_t * buf,
lv_coord_t buf_w,
lv_coord_t x,
lv_coord_t y,
lv_color_t color,
lv_opa_t opa)
{
/* buf should be disp_drv->buffer->buf_act */
if(buf == disp_drv->buffer->buf_act){
static const uint32_t px_size_rgb = sizeof(color.full);
static const uint32_t offset = LV_HOR_RES_MAX * LV_VER_RES_MAX * px_size_rgb;
uint32_t location = x + y * vinfo.xres;
lv_color_t color_buf;
lv_color_t color_mix;
color_buf.full = *(((uint16_t*)buf) + location);
color_buf.ext_ch.alpha = *(buf + offset + location);
lv_color_mix_with_alpha(
color_buf, (lv_opa_t) color_buf.ext_ch.alpha,
color, opa,
&color_mix, (lv_opa_t*)&color_mix.ext_ch.alpha);
/* RGB plane*/
*(((uint16_t*)buf) + location) = color_mix.full;
/* Alpha plane, 565 = 2 bytes, shift to alpha address */
*(buf + offset + location) = color_mix.ext_ch.alpha;
}
else{
LV_LOG_WARN("buf != disp_drv->buffer->buf_act");
}
}
void lv_gpu_nvt_dma2d_rotate_8565(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir)
{
UINT32 dst_pa = 0;
UINT32 src_pa = 0;
HD_GFX_ROTATE param = {0};
HD_RESULT ret = HD_OK;
HD_COMMON_MEM_VIRT_INFO vir_meminfo = {0};
lv_coord_t copy_w = (area.x2 - area.x1) + 1;
lv_coord_t copy_h = (area.y2 - area.y1) + 1;
bool swap_xy = false;
HD_IPOINT dst_pos = {-1, -1};
const uint8_t pixel_size_rgb = sizeof(LV_COLOR_BLACK.full);
const uint8_t pixel_size_alpha = sizeof(LV_COLOR_BLACK.ext_ch.alpha);
const uint32_t alpha_offset = LV_VER_RES_MAX * LV_HOR_RES_MAX * pixel_size_rgb;
/* convert va to pa */
vir_meminfo.va = (void *)(map);
if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) {
fbdev_msg("convert map failed!\n");
return;
}
src_pa = vir_meminfo.pa;
vir_meminfo.va = (void *)(buf);
if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) {
fbdev_msg("convert buf failed!\n");
return;
}
dst_pa = vir_meminfo.pa;
memset(&param, 0, sizeof(HD_GFX_ROTATE));
/* check dir */
switch(dir)
{
case HD_VIDEO_DIR_ROTATE_90:
dst_pos = (HD_IPOINT){LV_VER_RES_MAX - area.y1 - copy_h, area.x1};
swap_xy = true;
break;
case HD_VIDEO_DIR_ROTATE_270:
dst_pos = (HD_IPOINT){area.y1, LV_HOR_RES_MAX - area.x1 - copy_w};
swap_xy = true;
break;
case HD_VIDEO_DIR_ROTATE_180:
dst_pos = (HD_IPOINT){LV_HOR_RES_MAX - area.x1 - copy_w, LV_VER_RES_MAX - area.y1 - copy_h};
swap_xy = false;
break;
default:
LV_LOG_ERROR("dir(%lx) is currently not supported", dir);
return;
}
/* rotate rgb channels */
param.src_img.dim.w = LV_HOR_RES_MAX;
param.src_img.dim.h = LV_VER_RES_MAX;
param.src_img.p_phy_addr[0] = src_pa;
param.src_img.lineoffset[0] = LV_HOR_RES_MAX * pixel_size_rgb;
param.src_img.format = HD_VIDEO_PXLFMT_RGB565;
param.src_region.x = 0;
param.src_region.y = 0;
param.src_region.w = copy_w;
param.src_region.h = copy_h;
param.dst_img.format = HD_VIDEO_PXLFMT_RGB565;
param.dst_img.dim.w = swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX;
param.dst_img.dim.h = swap_xy ? LV_HOR_RES_MAX : LV_VER_RES_MAX;
param.dst_img.p_phy_addr[0] = dst_pa;
param.dst_img.lineoffset[0] = (swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX) * pixel_size_rgb;
param.dst_pos = dst_pos;
param.angle = dir;
ret = hd_gfx_rotate(&param);
if(ret != HD_OK){
fbdev_msg("ret = %d\n", ret);
}
/* rotate alpha channel */
param.src_img.dim.w = LV_HOR_RES_MAX;
param.src_img.dim.h = LV_VER_RES_MAX;
param.src_img.p_phy_addr[0] = src_pa + alpha_offset;
param.src_img.lineoffset[0] = LV_HOR_RES_MAX * pixel_size_alpha;
param.src_img.format = HD_VIDEO_PXLFMT_I8;
param.src_region.x = 0;
param.src_region.y = 0;
param.src_region.w = copy_w;
param.src_region.h = copy_h;
param.dst_img.format = HD_VIDEO_PXLFMT_I8;
param.dst_img.dim.w = swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX;
param.dst_img.dim.h = swap_xy ? LV_HOR_RES_MAX : LV_VER_RES_MAX;
param.dst_img.p_phy_addr[0] = dst_pa + alpha_offset;
param.dst_img.lineoffset[0] = (swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX) * pixel_size_alpha;
param.dst_pos = dst_pos;
param.angle = dir;
ret = hd_gfx_rotate(&param);
if(ret != HD_OK){
fbdev_msg("ret = %d\n", ret);
}
}
#endif
#include "kwrap/debug.h"
#include "FileSysTsk.h"
void lv_gpu_nvt_dma2d_rotate(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir, bool flush)
{
UINT32 dst_pa = 0;
UINT32 src_pa = 0;
HD_GFX_ROTATE param = {0};
HD_RESULT ret = HD_OK;
HD_COMMON_MEM_VIRT_INFO vir_meminfo = {0};
lv_coord_t copy_w = lv_area_get_width(&area);
lv_coord_t copy_h = lv_area_get_height(&area);
bool swap_xy = false;
HD_IPOINT dst_pos = {-1, -1};
/* convert va to pa */
vir_meminfo.va = (void *)(map);
if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) {
fbdev_msg("convert map failed!\n");
return;
}
src_pa = vir_meminfo.pa;
vir_meminfo.va = (void *)(buf);
if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) {
fbdev_msg("convert buf failed!\n");
return;
}
dst_pa = vir_meminfo.pa;
memset(&param, 0, sizeof(HD_GFX_ROTATE));
/* check dir */
switch(dir)
{
case HD_VIDEO_DIR_ROTATE_90:
dst_pos = (HD_IPOINT){LV_VER_RES_MAX - area.y1 - copy_h, area.x1};
swap_xy = true;
break;
case HD_VIDEO_DIR_ROTATE_270:
dst_pos = (HD_IPOINT){area.y1, LV_HOR_RES_MAX - area.x1 - copy_w};
swap_xy = true;
break;
case HD_VIDEO_DIR_ROTATE_180:
dst_pos = (HD_IPOINT){LV_HOR_RES_MAX - area.x1 - copy_w, LV_VER_RES_MAX - area.y1 - copy_h};
swap_xy = false;
break;
default:
LV_LOG_ERROR("dir(%lx) is currently not supported", dir);
return;
}
/* rotate rgb channels */
param.src_img.dim.w = copy_w;
param.src_img.dim.h = copy_h;
param.src_img.p_phy_addr[0] = src_pa;
param.src_img.lineoffset[0] = copy_w * sizeof(lv_color_t);
param.src_img.format = hdal_fmt;
param.src_region.x = 0;
param.src_region.y = 0;
param.src_region.w = copy_w;
param.src_region.h = copy_h;
param.dst_img.format = hdal_fmt;
param.dst_img.dim.w = swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX;
param.dst_img.dim.h = swap_xy ? LV_HOR_RES_MAX : LV_VER_RES_MAX;
param.dst_img.p_phy_addr[0] = dst_pa;
param.dst_img.lineoffset[0] = (swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX) * sizeof(lv_color_t);
param.dst_pos = dst_pos;
param.angle = dir;
if(flush){
ret = hd_gfx_rotate(&param);
}
else{
ret = vendor_gfx_rotate_no_flush(&param);
}
if(ret != HD_OK){
fbdev_msg("ret = %d\n", ret);
}
}
#endif
/**********************
* Local Functions
**********************/
#if LV_COLOR_DEPTH == 24
HD_RESULT disp_gfx_rotate_8565(UINT32 dst_pa, UINT32 src_pa, lv_disp_drv_t * disp_drv)
{
HD_GFX_ROTATE param;
HD_RESULT ret;
HD_VIDEO_PXLFMT fmt;
fmt = HD_VIDEO_PXLFMT_RGB565;
fbdev_msg("disp_gfx_rotate: dst_pa = 0x%x,src_pa = 0x%x fmt 0x%x\n", dst_pa,src_pa,fmt);
memset(&param, 0, sizeof(HD_GFX_ROTATE));
param.src_img.dim.w = disp_drv->hor_res;
param.src_img.dim.h = disp_drv->ver_res;
param.src_img.p_phy_addr[0] = src_pa;
param.src_img.lineoffset[0] = disp_drv->hor_res * 2;
param.src_img.format = fmt;
param.dst_img.dim.w = disp_drv->ver_res;
param.dst_img.dim.h = disp_drv->hor_res;
param.dst_img.p_phy_addr[0] = dst_pa;
param.dst_img.lineoffset[0] = disp_drv->ver_res * 2;
param.dst_img.format = fmt;
param.src_region.x = 0;
param.src_region.y = 0;
param.src_region.w = disp_drv->hor_res;
param.src_region.h = disp_drv->ver_res;
param.dst_pos.x = 0;
param.dst_pos.y = 0;
param.angle = VDO_ROTATE_DIR;
ret = hd_gfx_rotate(&param);
fmt = HD_VIDEO_PXLFMT_I8;
memset(&param, 0, sizeof(HD_GFX_ROTATE));
param.src_img.dim.w = disp_drv->hor_res;
param.src_img.dim.h = disp_drv->ver_res;
param.src_img.p_phy_addr[0] = src_pa + disp_drv->hor_res * disp_drv->ver_res * 2;
param.src_img.lineoffset[0] = disp_drv->hor_res;
param.src_img.format = fmt;
param.dst_img.dim.w = disp_drv->ver_res;
param.dst_img.dim.h = disp_drv->hor_res;
param.dst_img.p_phy_addr[0] = dst_pa + disp_drv->hor_res * disp_drv->ver_res * 2;
param.dst_img.lineoffset[0] = disp_drv->ver_res;
param.dst_img.format = fmt;
param.src_region.x = 0;
param.src_region.y = 0;
param.src_region.w = disp_drv->hor_res;
param.src_region.h = disp_drv->ver_res;
param.dst_pos.x = 0;
param.dst_pos.y = 0;
param.angle = VDO_ROTATE_DIR;
ret = hd_gfx_rotate(&param);
return ret;
}
#endif
#endif /* USE_FBDEV || USE_BSD_FBDEV */