Files
MXC_A59/lib/vg_driver/vg_driver_wrapper.c

525 lines
10 KiB
C

#include <stdarg.h>
#include "FreeRTOS.h"
#include "board.h"
#include "chip.h"
#include "rtos.h"
#include "romfile.h"
#include "vg_driver.h"
#if !defined(VG_ONLY) && !defined(AWTK)
#include "lvgl/lvgl.h"
#endif
#if LCD_ROTATE_ANGLE != LCD_ROTATE_ANGLE_0
#define VG_USE_LCD_TMP_BUFFER
#endif
#ifdef VG_USE_LCD_TMP_BUFFER
static void *xm_vg_tmp_lcd_buf = NULL;
static uint32_t xm_vg_get_tmp_lcd_buffer (void)
{
if(!xm_vg_tmp_lcd_buf) {
u32 width = (VG_OSD_W + 0xF) & (~0xF);
u32 height = (VG_OSD_H + 0xF) & (~0xF);
xm_vg_tmp_lcd_buf = (void *)pvPortMalloc(width * height * VG_BPP / 8);
}
if(!xm_vg_tmp_lcd_buf) {
printf("%s, pvPortMalloc failed\n", __FUNCTION__);
return 0;
}
return (uint32_t)xm_vg_tmp_lcd_buf;
}
static void xm_vg_release_tmp_lcd_buffer (void)
{
if(xm_vg_tmp_lcd_buf)
vPortFree(xm_vg_tmp_lcd_buf);
xm_vg_tmp_lcd_buf = NULL;
}
#endif
#ifdef VG_DRIVER
#include "xm_base.h"
uint32_t FS_FWrite(const void * pData, uint32_t Size, uint32_t N, void * pFile)
{
return 0;
}
int32_t FS_FTell(void * pFile)
{
return 0;
}
unsigned int xm_vg_get_width (void)
{
return VG_W;
}
unsigned int xm_vg_get_height (void)
{
return VG_H;
}
unsigned int xm_vg_get_stride (void)
{
return VG_OSD_W * VG_BPP / 8;
}
unsigned int xm_vg_get_bpp (void)
{
return VG_BPP;
}
#if defined(REVERSE_TRACK)
int xm_vg_is_valid_gpu_fb (unsigned int base)
{
int i;
for (i = 0; i < VIDEO_DISPLAY_BUF_NUM; i++) {
unsigned fb_base = ulVideoDisplayGetBufferAddr(i);
unsigned vg_base = fb_base + VG_Y * VG_OSD_W * VG_BPP / 8 + VG_X * VG_BPP / 8;
if (base == vg_base)
return 1;
}
return 0;
}
#else
int xm_vg_is_valid_gpu_fb (unsigned int base)
{
unsigned fb_base = ark_lcd_get_virt_addr();
unsigned vg_base = fb_base + VG_Y * VG_OSD_W * VG_BPP / 8 + VG_X * VG_BPP / 8;
if (base == vg_base || base == vg_base + xm_vg_get_stride() * VG_OSD_H)
return 1;
return 0;
}
#endif
void* XM_RomAddress (const char *src)
{
if (!src || src[0] == '\0') return NULL;
void *ptr;
RomFile *file = RomFileOpen(src);
if (!file) {
printf("open romfile %s fail.\n", src);
return NULL;
}
RomFileRead(file, NULL, file->size);
ptr = file->buf;
#ifndef ROMFILE_USE_SMALL_MEM
RomFileClose(file);
#endif
return ptr;
}
#ifdef LVGL_VG_GPU
unsigned int xm_vg_require_gpu_fb (void)
{
lv_disp_t * disp = lv_disp_get_default();
unsigned int vg_frame_base = 0;
if (disp) {
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
lv_color_t * disp_buf = vdb->buf_act;
vg_frame_base = (unsigned int)disp_buf;
} else {
vg_frame_base = ark_lcd_get_virt_addr();
}
vg_frame_base += VG_Y * VG_OSD_W * VG_BPP / 8 + VG_X * VG_BPP / 8;
return vg_frame_base;
}
#else
#if defined(VG_ONLY)
static int fb_index = 0;
unsigned int xm_vg_require_gpu_fb (void)
{
#ifdef VG_USE_LCD_TMP_BUFFER
return xm_vg_get_tmp_lcd_buffer();
#else
unsigned fb_base = ark_lcd_get_virt_addr();
fb_base += fb_index * VG_OSD_W * VG_OSD_H * VG_BPP / 8;
return fb_base;
#endif
}
void xm_vg_release_gpu_fb (void)
{
#ifdef VG_USE_LCD_TMP_BUFFER
#else
unsigned fb_base = xm_vg_require_gpu_fb();
CP15_clean_dcache_for_dma((uint32_t)fb_base, VG_OSD_W * VG_OSD_H * VG_BPP / 8 + (uint32_t)fb_base);
ark_lcd_set_osd_yaddr(LCD_UI_LAYER, (unsigned int)fb_base);
ark_lcd_set_osd_sync(LCD_UI_LAYER);
ark_lcd_wait_for_vsync();
fb_index = (fb_index + 1) & 1;
#endif
}
// 获取当前正在渲染的OSD framebuffer
// *no == -1 表示获取当前正在渲染的OSD framebuffer
// 返回值
// 当前正在渲染的OSD framebuffer基址
unsigned int xm_vg_get_osd_fb (int *no)
{
unsigned fb_base = ark_lcd_get_virt_addr();
fb_base += fb_index * VG_OSD_W * VG_OSD_H * VG_BPP / 8;
if(*no == (-1))
{
*no = fb_index;
return fb_base;
}
else
{
if(*no >= 2)
return 0;
else
return fb_base;
}
}
#elif defined(AWTK)
#include "fb_queue.h"
static fb_queue_s *curr_fb = NULL;
unsigned int xm_vg_require_gpu_fb (void)
{
fb_queue_s *fb_unit = NULL;
while (!fb_unit)
{
fb_unit = fb_queue_get_free_unit();
if(fb_unit)
break;
OS_Delay (1);
}
curr_fb = fb_unit;
//XM_lock();
//printf ("req %x\n", fb_unit->fb_base);
//XM_unlock();
return fb_unit->fb_base;
}
void xm_vg_release_gpu_fb (void)
{
fb_queue_s *fb_unit = curr_fb;
if(fb_unit)
{
curr_fb = NULL;
fb_queue_set_ready (fb_unit);
//XM_lock();
//printf ("rdy %x\n", fb_unit->fb_base);
//XM_unlock();
}
}
#elif defined(REVERSE_TRACK)
static unsigned int gpu_fb_addr = 0;
void xm_vg_set_gpu_fb_addr(unsigned int addr)
{
gpu_fb_addr = addr;
}
unsigned int xm_vg_require_gpu_fb (void)
{
unsigned int vg_frame_base;
vg_frame_base = gpu_fb_addr ? gpu_fb_addr : ulVideoDisplayGetBufferAddr(0);
vg_frame_base += VG_Y * VG_OSD_W * VG_BPP / 8 + VG_X * VG_BPP / 8;
return vg_frame_base;
}
#else
unsigned int xm_vg_require_gpu_fb (void)
{
lv_disp_t * disp = lv_disp_get_default();
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
lv_color_t * disp_buf = vdb->buf_act;
unsigned int vg_frame_base = (unsigned int)disp_buf;
vg_frame_base += VG_Y * VG_OSD_W * VG_BPP / 8 + VG_X * VG_BPP / 8;
return vg_frame_base;
}
#endif
#endif
int xm_vg_get_offset_x (void)
{
return VG_X;
}
int xm_vg_get_offset_y (void)
{
return VG_Y;
}
unsigned int xm_vg_get_osd_stride (void)
{
return VG_OSD_W * VG_BPP / 8;
}
void xm_vg_get_osd_window ( unsigned int* x,
unsigned int* y,
unsigned int* w,
unsigned int* h,
unsigned int* stride
)
{
*x = VG_X;
*y = VG_Y;
*w = VG_W;
*h = VG_H;
*stride = xm_vg_get_stride();
}
void* xm_vg_get_gpu_background_image (void)
{
static RomFile *bgfile = NULL;
if(!bgfile) {
bgfile = RomFileOpen("vg_bg.rgb");
if (!bgfile)
return NULL;
RomFileRead(bgfile, NULL, bgfile->size);
}
char *bk = (char*)bgfile->buf;
if(bk)
bk += (VG_H - 1) * VG_W * VG_BPP / 8;
return (void *)bk;
}
unsigned int vg_get_framebuffer (void)
{
return xm_vg_require_gpu_fb();
}
#ifndef LVGL_VG_GPU
#if defined(VG_ONLY) || defined(AWTK)
#if defined(DOUBLE_POINTER_HALO)
extern int double_pointer_halo_init (int width, int height);
extern int double_pointer_halo_draw (void);
#elif defined(SINGLE_POINTER_HALO)
extern int single_pointer_halo_init (int width, int height);
extern int single_pointer_halo_draw (void);
#elif defined(AWTK)
extern int gui_app_start(int lcd_w, int lcd_h);
#endif
#include <stdlib.h>
int xm_vg_loop (void *context)
{
#ifdef AWTK
#ifdef WITH_VGCANVAS
gui_app_start (xm_vg_get_width(), xm_vg_get_height());
#else
gui_app_start (OSD_WIDTH, OSD_HEIGHT);
#endif
return 0;
#else
int frame_count = 0;
int vg_draw_tickets = 0; // 累加VG时间
int vsync_delay_tickets = 0; // 累加LCD帧同步等待时间
#if defined(DOUBLE_POINTER_HALO)
double_pointer_halo_init(xm_vg_get_width(), xm_vg_get_height());
#elif defined(SINGLE_POINTER_HALO)
single_pointer_halo_init(xm_vg_get_width(), xm_vg_get_height());
#endif
unsigned int start_ticket = XM_GetTickCount();
while(1)
{
// 获取当前正在渲染使用的OSD framebuffer基址及序号
//int fb_no = -1;
//unsigned int fb_base = xm_vg_get_osd_fb(&fb_no);
int t1 = get_timer(0);
#if defined(DOUBLE_POINTER_HALO)
double_pointer_halo_draw();
#elif defined(SINGLE_POINTER_HALO)
single_pointer_halo_draw();
#endif
int t2 = get_timer(0);
vg_draw_tickets += abs(t2 - t1);
#ifdef VG_USE_LCD_TMP_BUFFER
static int fb_index = 0;
unsigned int fb_base = ark_lcd_get_virt_addr();
fb_base += fb_index * VG_OSD_W * VG_OSD_H * VG_BPP / 8;
uint32_t src_addr = xm_vg_get_tmp_lcd_buffer();
CP15_invalidate_dcache_for_dma((uint32_t)fb_base, VG_OSD_W * VG_OSD_H * VG_BPP / 8 + (uint32_t)fb_base);
pxp_scaler_rotate(src_addr, 0, 0,
PXP_SRC_FMT_RGB565, VG_OSD_W, VG_OSD_H,
(uint32_t)fb_base, 0, PXP_OUT_FMT_RGB565, LCD_WIDTH, LCD_HEIGHT, LCD_ROTATE_ANGLE);
ark_lcd_set_osd_yaddr(LCD_UI_LAYER, (unsigned int)fb_base);
ark_lcd_set_osd_sync(LCD_UI_LAYER);
ark_lcd_wait_for_vsync();
fb_index != fb_index;
#else
// 释放当前渲染的GPU帧, 并等待LCD刷新该帧
xm_vg_release_gpu_fb ();
#endif
int t3 = get_timer(0);
vsync_delay_tickets += abs(t3 - t2);
frame_count ++;
if(frame_count == 1000)
{
unsigned int t = XM_GetTickCount() - start_ticket;
printf ("fps = %4.1f , vg_ticket = %d us, vsync_delay_ticket = %d us\r\n", 1000.0*1000.0 / t, vg_draw_tickets / 1000, vsync_delay_tickets / 1000);
vg_draw_tickets = 0;
vsync_delay_tickets = 0;
frame_count = 0;
start_ticket = XM_GetTickCount();
}
//OS_Delay(1);
}
//double_pointer_halo_exit();
//vgFinish();
#ifdef VG_USE_LCD_TMP_BUFFER
xm_vg_release_tmp_lcd_buffer();
#endif
return 0;
#endif
}
#else
#ifdef REVERSE_TRACK
static int track_index = 0;
#else
static int pointer_halo_speed = 0;
#endif
static TaskHandle_t vg_task = NULL;
QueueHandle_t vg_done;
void xm_vg_draw_prepare(void *para)
{
if (para == NULL)
return;
#ifdef REVERSE_TRACK
track_index = *(int*)para;
#else
pointer_halo_speed = *(int*)para;
#endif
}
void xm_vg_draw_start(void)
{
if (vg_done)
xQueueReset(vg_done);
if (vg_task)
xTaskNotify(vg_task, 1, eSetValueWithOverwrite);
if (vg_done)
xQueueReceive(vg_done, NULL, portMAX_DELAY);
}
#ifdef REVERSE_TRACK
extern int reversing_auxiliary_line_init (int width, int height);
extern int reversing_auxiliary_line_draw (int index);
#else
extern int pointer_halo_init (int width, int height);
extern int pointer_halo_draw (int speed);
#endif
int xm_vg_loop (void *context)
{
uint32_t ulNotifiedValue;
//uint32_t stick = xTaskGetTickCount();
//uint32_t framecount = 0;
vg_task = xTaskGetCurrentTaskHandle();
vg_done = xQueueCreate(1, 0);
#ifdef REVERSE_TRACK
reversing_auxiliary_line_init(xm_vg_get_width(), xm_vg_get_height());
#else
pointer_halo_init(xm_vg_get_width(), xm_vg_get_height());
#endif
while(1)
{
xTaskNotifyWait( 0x00, /* Don't clear any notification bits on entry. */
0xffffffff, /* Reset the notification value to 0 on exit. */
&ulNotifiedValue, /* Notified value pass out in ulNotifiedValue. */
portMAX_DELAY);
#ifdef REVERSE_TRACK
reversing_auxiliary_line_draw(track_index);
#else
pointer_halo_draw(pointer_halo_speed);
#endif
/* if (++framecount == 1000) {
uint32_t tick = xTaskGetTickCount();
printf("fps %d.\n", 1000 * 1000 / (tick - stick));
framecount = 0;
stick = xTaskGetTickCount();
} */
xQueueSend(vg_done, NULL, 0);
}
#ifdef REVERSE_TRACK
//reversing_auxiliary_line_exit();
#else
//pointer_halo_exit();
#endif
//vgFinish();
return 0;
}
#endif
#endif
#ifdef LVGL_VG_GPU
extern void lvgl_thread(void *data);
int xm_vg_loop (void *context)
{
lvgl_thread(NULL);
return 0;
}
#endif
#endif