Files
gk-sdk/sample/tde/sample_tde.c
T

471 lines
13 KiB
C
Executable File

/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <math.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include "sample_comm.h"
#include "sample_comm_vo.h"
#include "xmedia_vo.h"
#include "xmedia_mmz.h"
#include "xmedia_tde.h"
#include "gfbg.h"
typedef struct{
xmedia_u8 *mmap_vir;
xmedia_u32 size;
}fb_mmap_info;
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
static const xmedia_char *g_image_names[] =
{
"res/apple.bits",
"res/applets.bits",
"res/calendar.bits",
"res/foot.bits",
"res/gmush.bits",
"res/gimp.bits",
"res/gsame.bits",
"res/keys.bits"
};
#define BACKGROUND_NAME "res/background.bits"
#define N_IMAGES (xmedia_s32)((sizeof (g_image_names) / sizeof (g_image_names[0])))
#define SCREEN_WIDTH 720
#define SCREEN_HEIGHT 480
#define CYCLE_LEN 60
xmedia_s32 g_fb_fd = -1;
xmedia_s32 g_vo_dev = 0;
xmedia_s32 g_vo_layer = 0;
xmedia_s32 g_vo_chn[1] = {0};
xmedia_s32 g_vo_chn_num = 1;
xmedia_tde_surface_info *g_fb_background_surface = XMEDIA_NULL;
xmedia_tde_surface_info *g_fb_images[N_IMAGES] = {0};
fb_mmap_info g_fb_mmap_info = {0};
xmedia_bool g_tde_exit = XMEDIA_FALSE;
static xmedia_void *process_keyboard(xmedia_void *arg)
{
xmedia_char ch;
xmedia_bool *status = (xmedia_bool *) arg;
printf("press q to quit\n");
printf("press s to suspend and resume\n");
while (1) {
ch = getchar();
if (ch == 's') {
system("echo mem > /sys/power/state"); // 进入休眠状态 之后自动唤醒
} else if (ch == 'q') {
*status = XMEDIA_TRUE;
break;
} else {
printf("press q to quit\n");
printf("press s to suspend and resume\n");
}
}
return XMEDIA_NULL;
}
static xmedia_void tde_destroy_surface(xmedia_tde_surface_info *sur_info)
{
if (sur_info->surface.phys_addr[0] == 0) {
return;
}
xmedia_mmz_free(sur_info->surface.phys_addr[0]);
return;
}
void sample_tde_handle_sig(xmedia_s32 signo)
{
if (signo == SIGINT || signo == SIGTERM) {
// 处理资源泄露
for (xmedia_s32 i = 0; i < N_IMAGES; i++) {
if (g_fb_images[i] != XMEDIA_NULL) {
tde_destroy_surface(g_fb_images[i]);
}
}
if (g_fb_background_surface != XMEDIA_NULL) {
tde_destroy_surface(g_fb_background_surface);
}
if(g_fb_mmap_info.mmap_vir != XMEDIA_NULL){
munmap(g_fb_mmap_info.mmap_vir, g_fb_mmap_info.size);
g_fb_mmap_info.mmap_vir = XMEDIA_NULL;
}
if (g_fb_fd != -1) {
close(g_fb_fd);
}
xmedia_tde_exit();
sample_comm_vo_stop(g_vo_dev, g_vo_layer, g_vo_chn, g_vo_chn_num);
xmedia_vo_exit();
printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
}
exit(-1);
}
static xmedia_void circumrotate (xmedia_tde_surface_info *bg, xmedia_tde_surface_info *image,
xmedia_tde_surface_info *dst, xmedia_u32 cur_on_show)
{
xmedia_s32 ret;
xmedia_s32 handle;
xmedia_tde_surface_info *dst_sur_tmp = (cur_on_show == 0) ? dst + 1 : dst;
xmedia_tde_surface_info dst_sur = {0};
static xmedia_s32 frame_num = 0;
xmedia_float f;
xmedia_float x_mid, y_mid;
xmedia_float radius;
xmedia_s32 i;
xmedia_tde_operation_attr opt = {0};
memcpy(&dst_sur, dst_sur_tmp, sizeof(xmedia_tde_surface_info));
opt.blend_en = XMEDIA_TRUE;
opt.blend_attr.pixel_alpha_en = XMEDIA_TRUE;
opt.blend_attr.blend_mode = XMEDIA_TDE_BLEND_MODE_SRCOVER;
ret = xmedia_tde_create_job(&handle);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("xmedia_tde_create_job failed !\n");
return;
}
bg->rect.x = 0;
bg->rect.y = 0;
bg->rect.width = SCREEN_WIDTH;
bg->rect.height = SCREEN_HEIGHT;
f = (float) (frame_num % CYCLE_LEN) / CYCLE_LEN;
x_mid = bg->rect.width / 2.16f;
y_mid = bg->rect.height / 2.304f;
radius = MIN (x_mid, y_mid) / 2.0f;
ret = xmedia_tde_add_task_single_blit(handle, bg, &dst_sur, 0, XMEDIA_NULL);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("xmedia_tde_add_task_single_blit failed !\n");
xmedia_tde_cancel_job(handle);
return;
}
for(i = 0; i < N_IMAGES; i++) {
xmedia_float ang;
xmedia_float r;
ang = 2.0f * (xmedia_float) M_PI * (xmedia_float) i / N_IMAGES - f * 2.0f * (xmedia_float) M_PI;
r = radius + (radius / 3.0f) * sinf (f * 2.0 * M_PI);
dst_sur.rect.x = x_mid + r * cosf (ang) - image[i].surface.width / 2.0f;
dst_sur.rect.x = x_mid + r * cosf (ang) - image[i].surface.width / 2.0f;;
dst_sur.rect.y = y_mid + r * sinf (ang) - image[i].surface.height / 2.0f;
dst_sur.rect.width = image[i].surface.width;
dst_sur.rect.height = image[i].surface.height;
/* 4. bitblt image to screen */
ret = xmedia_tde_add_task_double_blit(handle, &dst_sur, &image[i], &dst_sur, &opt);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("xmedia_tde_add_task_double_blit failed !\n");
xmedia_tde_cancel_job(handle);
return;
}
}
ret = xmedia_tde_submit_job(handle);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("xmedia_tde_submit_job failed !\n");
xmedia_tde_cancel_job(handle);
return;
}
frame_num++;
return;
}
static xmedia_s32 tde_create_surface_by_file(const xmedia_char *file_name,
xmedia_tde_surface_info *sur_info)
{
FILE *fp;
xmedia_u32 buffer_length = 0;
xmedia_u8 *vir_addr;
if (file_name == XMEDIA_NULL || sur_info == XMEDIA_NULL) {
SAMPLE_PRT("NULL ptr!\n");
return -1;
}
fp = fopen(file_name, "rb");
if (fp == XMEDIA_NULL) {
SAMPLE_PRT("fopen FILE:%s!\n", file_name);
return -1;
}
fread(&sur_info->surface.pixel_format, 1, 4, fp);
fread(&sur_info->surface.width, 1, 4, fp);
fread(&sur_info->surface.height, 1, 4, fp);
fread(&sur_info->surface.stride[0], 1, 4, fp);
buffer_length = sur_info->surface.stride[0] * sur_info->surface.height;
if (buffer_length > 0x7FFFFFFF) {
SAMPLE_PRT("fopen FILE:%s!\n", file_name);
fclose(fp);
return -1;
}
// 分配mmz内存
sur_info->surface.phys_addr[0] = xmedia_mmz_alloc(XMEDIA_NULL, XMEDIA_NULL, buffer_length);
if (sur_info->surface.phys_addr[0] == 0) {
SAMPLE_PRT("xmedia_mmz_alloc failed!\n");
fclose(fp);
return -1;
}
vir_addr = xmedia_mmz_map(sur_info->surface.phys_addr[0], buffer_length, XMEDIA_FALSE);
if (vir_addr == 0) {
SAMPLE_PRT("xmedia_mmz_map failed!\n");
xmedia_mmz_free(sur_info->surface.phys_addr[0]);
fclose(fp);
return -1;
}
fread(vir_addr, 1, buffer_length, fp); // 图片是标准大小,自然对齐
sur_info->surface.alpha0 = 0x0;
sur_info->surface.alpha1 = 0xff;
sur_info->surface.is_alpha_ext_1555 = XMEDIA_TRUE;
sur_info->rect.x = 0;
sur_info->rect.y = 0;
sur_info->rect.width = sur_info->surface.width;
sur_info->rect.height = sur_info->surface.height;
xmedia_mmz_unmap((void *)vir_addr);
fclose(fp);
return XMEDIA_SUCCESS;
}
static xmedia_void tde_get_suface_by_fix_info(struct fb_fix_screeninfo *fix_info,
xmedia_tde_surface_info *sur_info, xmedia_u32 index)
{
sur_info->surface.alpha0 = 0x0;
sur_info->surface.alpha1 = 0xff;
sur_info->surface.clut_phys_addr = 0;
sur_info->surface.clut_reload = XMEDIA_FALSE;
sur_info->surface.is_alpha_ext_1555 = XMEDIA_TRUE;
sur_info->surface.pixel_format = XMEDIA_VIDEO_PIXEL_FMT_ARGB_1555;
sur_info->surface.width = SCREEN_WIDTH;
sur_info->surface.height = SCREEN_HEIGHT;
sur_info->surface.stride[0] = SCREEN_WIDTH * 2;
sur_info->surface.phys_addr[0] = (index == 0) ? fix_info->smem_start : fix_info->smem_start + SCREEN_WIDTH * 2 *
SCREEN_HEIGHT;
sur_info->rect.x = 0;
sur_info->rect.y = 0;
sur_info->rect.width = sur_info->surface.width;
sur_info->rect.height = sur_info->surface.height;
return;
}
xmedia_s32 tde_draw_graphic_sample(xmedia_void)
{
xmedia_s32 ret = 0;
xmedia_s32 i, j;
xmedia_u32 times = 0;
xmedia_s32 fb_fd;
gfbg_drv_alpha fb_alpha = {0};
struct fb_var_screeninfo var_info = {0};
struct fb_fix_screeninfo fix_info = {0};
struct fb_bitfield red32 = {10, 5, 0};
struct fb_bitfield green32 = {5, 5, 0};
struct fb_bitfield blue32 = {0, 5, 0};
struct fb_bitfield alpha32 = {15, 1, 0};
xmedia_u8 *fb_mmap_vir = XMEDIA_NULL;
xmedia_bool state = XMEDIA_TRUE;
xmedia_tde_surface_info bg = {0};
xmedia_tde_surface_info image[8] = {0};
xmedia_tde_surface_info dst[2] = {0};
fb_fd = open("/dev/fb0", O_RDWR);
if (fb_fd < 0) {
SAMPLE_PRT("open fb0 failed !\n");
goto GRAPHIC_FAIL0;
}
g_fb_fd = fb_fd;
ret = ioctl(fb_fd, GFBG_PUT_ALPHA, &fb_alpha);
if (ret < 0) {
SAMPLE_PRT("Put alpha info failed !\n");
goto GRAPHIC_FAIL1;
}
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var_info) < 0) {
SAMPLE_PRT("Get variable screen info failed!\n");
goto GRAPHIC_FAIL1;
}
var_info.xres_virtual = SCREEN_WIDTH;
var_info.yres_virtual = SCREEN_HEIGHT * 2;
var_info.xres = SCREEN_WIDTH;
var_info.yres = SCREEN_HEIGHT;
var_info.activate = FB_ACTIVATE_NOW;
var_info.bits_per_pixel = 16;
var_info.xoffset = 0;
var_info.yoffset = 0;
var_info.red = red32;
var_info.green = green32;
var_info.blue = blue32;
var_info.transp = alpha32;
if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &var_info) < 0) {
SAMPLE_PRT("FBIOPUT_VSCREENINFO error\n");
goto GRAPHIC_FAIL1;
}
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix_info) < 0) {
SAMPLE_PRT("FBIOGET_FSCREENINFO error\n");
goto GRAPHIC_FAIL1;
}
fb_mmap_vir = mmap(NULL, fix_info.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
if (fb_mmap_vir == XMEDIA_NULL) {
SAMPLE_PRT("mmap fb0 failed!\n");
goto GRAPHIC_FAIL1;
}
memset(fb_mmap_vir, 0x00, fix_info.smem_len);
g_fb_mmap_info.mmap_vir = fb_mmap_vir;
g_fb_mmap_info.size = fix_info.smem_len;
ret = tde_create_surface_by_file(BACKGROUND_NAME, &bg);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("create bg surface failed!\n");
goto GRAPHIC_FAIL2;
}
g_fb_background_surface = &bg;
for (i = 0; i < N_IMAGES; i++) {
ret = tde_create_surface_by_file(g_image_names[i], &image[i]);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("create image[%d] surface failed!\n", i);
for (j = i; j > 0; j--) {
tde_destroy_surface(&image[j - 1]);
}
goto GRAPHIC_FAIL3;
}
g_fb_images[i]= &image[i];
}
tde_get_suface_by_fix_info(&fix_info, &dst[0], 0);
tde_get_suface_by_fix_info(&fix_info, &dst[1], 1);
if (ioctl(fb_fd, GFBG_PUT_SHOW, &state) < 0) {
SAMPLE_PRT("FBIOPUT_SHOW failed!\n");
goto GRAPHIC_FAIL4;
}
do {
circumrotate(&bg, image, dst, times % 2);
var_info.yoffset = (times % 2) ? 0 : 480;
if (ioctl(fb_fd, FBIOPAN_DISPLAY, &var_info) < 0) {
SAMPLE_PRT("FBIOPAN_DISPLAY error\n");
goto GRAPHIC_FAIL4;
}
times++;
sleep(1);
} while (g_tde_exit == XMEDIA_FALSE && times < 20);
SAMPLE_PRT("exit\n");
ret = XMEDIA_SUCCESS;
GRAPHIC_FAIL4:
for (j = N_IMAGES; j > 0; j--) {
tde_destroy_surface(&image[j - 1]);
}
GRAPHIC_FAIL3:
tde_destroy_surface(&bg);
GRAPHIC_FAIL2:
munmap(fb_mmap_vir, fix_info.smem_len);
fb_mmap_vir = XMEDIA_NULL;
GRAPHIC_FAIL1:
close(fb_fd);
fb_fd = -1;
GRAPHIC_FAIL0:
return ret;
}
int main()
{
xmedia_s32 ret;
sample_vo_config_input vo_input = {0};
sample_vo_config vo_config = {0};
pthread_t t1;
signal(SIGINT, sample_tde_handle_sig);
signal(SIGTERM, sample_tde_handle_sig);
ret = xmedia_vo_init();
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("vo init failed !\n");
goto FAIL0;
}
vo_input.intf_sync = XMEDIA_VO_INTF_SYNC_1080P30;
vo_input.intf_type = XMEDIA_INTF_TYPE_BT1120;
vo_input.square_sort = 1;
ret = sample_comm_vo_get_default_config(vo_input, &vo_config);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("get vo default config failed !\n");
goto FAIL1;
}
ret = sample_comm_vo_start(g_vo_dev, g_vo_layer, g_vo_chn, g_vo_chn_num, XMEDIA_FALSE, &vo_config);
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("vo start failed !\n");
goto FAIL1;
}
ret = xmedia_tde_init();
if (ret != XMEDIA_SUCCESS) {
SAMPLE_PRT("tde init failed !\n");
goto FAIL2;
}
pthread_create(&t1, XMEDIA_NULL, process_keyboard, &g_tde_exit);
pthread_detach(t1);
ret = tde_draw_graphic_sample();
if(ret != XMEDIA_SUCCESS) {
goto FAIL3;
}
ret = XMEDIA_SUCCESS;
FAIL3:
xmedia_tde_exit();
FAIL2:
sample_comm_vo_stop(g_vo_dev, g_vo_layer, g_vo_chn, g_vo_chn_num);
FAIL1:
xmedia_vo_exit();
FAIL0:
return ret;
}