mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
379 lines
10 KiB
C
379 lines
10 KiB
C
/*
|
|
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: ZeQuan Liang <zequan.liang@artinchip.com>
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
|
|
#include <aic_core.h>
|
|
|
|
#include "./public/bmp.h"
|
|
#include "./public/ge_fb.h"
|
|
#include "./public/ge_mem.h"
|
|
|
|
/* ge dither test */
|
|
#define SRC_DISP_REGION 0
|
|
#define DST_DISP_REGION 1
|
|
|
|
#define LOGE(fmt, ...) aic_log(AIC_LOG_ERR, "E", fmt, ##__VA_ARGS__)
|
|
#define LOGW(fmt, ...) aic_log(AIC_LOG_WARN, "W", fmt, ##__VA_ARGS__)
|
|
#define LOGI(fmt, ...) aic_log(AIC_LOG_INFO, "I", fmt, ##__VA_ARGS__)
|
|
|
|
/* str to format table struct */
|
|
struct StrToFormat {
|
|
char *str;
|
|
int format;
|
|
};
|
|
|
|
/* format conversion */
|
|
static int table_size = 0;
|
|
static struct StrToFormat *format_table = NULL;
|
|
|
|
static char g_src_input[128] = {"/sdcard/ge_test/image/singer_alpha.bmp"};
|
|
|
|
static void usage(char *app)
|
|
{
|
|
printf("Usage: %s [Options]: \n", app);
|
|
printf("\t-o, --dither_on, Select open dither (default 0), 0 :close 1 :open\n");
|
|
printf("\t-s, --src_format, Select src format (default argb8888)\n");
|
|
printf("\t-d, --dst_format, Select dst format (default argb4444)\n");
|
|
printf("\t-i --input_src, input src\n");
|
|
printf("\t-u, --usage\n");
|
|
printf("\t-h, --help, list the supported format and the test instructions\n\n");
|
|
|
|
printf("\tfor example:\n");
|
|
printf("\tge_dither -i /data/singer_alpha.bmp -o 1\n");
|
|
}
|
|
|
|
static void help(void)
|
|
{
|
|
printf("\r--This is ge bitblt operation using dither function.\n");
|
|
printf("\r--Dither supports input argb8888 and rgb888 formats, and output, argb4444, argb1555 and rgb565 formats.\n");
|
|
printf("\r--In this example, the input layer is src, output layer is dst.\n");
|
|
printf("\r--Please use parameter -u or --usage to list other parameters.\n\n");
|
|
}
|
|
|
|
static int str_to_format(char *str)
|
|
{
|
|
int i = 0;
|
|
static struct StrToFormat table[] = {
|
|
{"argb8888", MPP_FMT_ARGB_8888},
|
|
{"argb4444", MPP_FMT_ARGB_4444},
|
|
{"rgb565", MPP_FMT_RGB_565},
|
|
{"argb1555", MPP_FMT_ARGB_1555},
|
|
{"rgb888", MPP_FMT_RGB_888}
|
|
};
|
|
format_table = &(*table);
|
|
table_size = sizeof(table) / sizeof(table[0]);
|
|
for (i = 0; i < table_size; i++) {
|
|
if (!strncmp(str, table[i].str, strlen(table[i].str)))
|
|
return table[i].format;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static long long int str2int(char *_str)
|
|
{
|
|
if (_str == NULL) {
|
|
pr_err("The string is empty!\n");
|
|
return -1;
|
|
}
|
|
|
|
if (strncmp(_str, "0x", 2))
|
|
return atoi(_str);
|
|
else
|
|
return strtoll(_str, NULL, 16);
|
|
}
|
|
|
|
static int bitblt_run(struct mpp_ge *ge, struct ge_bitblt *blt)
|
|
{
|
|
int ret = 0;
|
|
|
|
ret = mpp_ge_bitblt(ge, blt);
|
|
if (ret < 0) {
|
|
LOGE("bitblt task failed\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = mpp_ge_emit(ge);
|
|
if (ret < 0) {
|
|
LOGE("emit task failed\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = mpp_ge_sync(ge);
|
|
if (ret < 0) {
|
|
LOGE("ge sync fail\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void display_set(struct ge_bitblt *blt, struct ge_fb_info *fb_info, struct ge_buf *buffer, int region)
|
|
{
|
|
unsigned int fb_phy = 0;
|
|
int dstx = 0;
|
|
int dsty = 0;
|
|
|
|
memset(blt, 0, sizeof(struct ge_bitblt));
|
|
|
|
if (region == SRC_DISP_REGION) {
|
|
dstx = 0;
|
|
dsty = 0;
|
|
} else {
|
|
dstx = fb_info->fb_data.width / 2;
|
|
dsty = 0;
|
|
}
|
|
|
|
/* Src layer set */
|
|
memcpy(&blt->src_buf, &buffer->buf, sizeof(struct mpp_buf));
|
|
blt->src_buf.crop_en = 0;
|
|
|
|
fb_phy = fb_get_cur_frame(fb_info);
|
|
/* Dst layer set */
|
|
blt->dst_buf.buf_type = MPP_PHY_ADDR;
|
|
blt->dst_buf.phy_addr[0] = fb_phy;
|
|
blt->dst_buf.stride[0] = fb_info->fb_data.stride;
|
|
blt->dst_buf.size.width = fb_info->fb_data.width;
|
|
blt->dst_buf.size.height = fb_info->fb_data.height;
|
|
blt->dst_buf.format = fb_info->fb_data.format;
|
|
blt->dst_buf.crop_en = 1;
|
|
blt->dst_buf.crop.x = dstx;
|
|
blt->dst_buf.crop.y = dsty;
|
|
blt->dst_buf.crop.width = fb_info->fb_data.width / 2;
|
|
blt->dst_buf.crop.height = fb_info->fb_data.height;
|
|
}
|
|
|
|
static int display(struct mpp_ge *ge, struct ge_bitblt *blt, struct ge_fb_info *fb_info, struct ge_buf *buffer, int region)
|
|
{
|
|
int ret = 0;
|
|
|
|
display_set(blt, fb_info, buffer, region);
|
|
|
|
ret = bitblt_run(ge, blt);
|
|
if (ret < 0) {
|
|
LOGE("bitblt_run failed\n");
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void bmp_to_src_set(struct ge_bitblt *blt, struct ge_buf *bmp_buffer, struct ge_buf *src_buffer)
|
|
{
|
|
memset(blt, 0, sizeof(struct ge_bitblt));
|
|
|
|
memcpy(&blt->src_buf, &bmp_buffer->buf, sizeof(struct mpp_buf));
|
|
blt->src_buf.crop_en = 0;
|
|
|
|
memcpy(&blt->dst_buf, &src_buffer->buf, sizeof(struct mpp_buf));
|
|
blt->dst_buf.crop_en = 0;
|
|
}
|
|
|
|
static int bmp_to_src_run(struct mpp_ge *ge, struct ge_bitblt *blt, struct ge_buf *bmp_buffer, struct ge_buf *src_buffer)
|
|
{
|
|
int ret = -1;
|
|
|
|
bmp_to_src_set(blt, bmp_buffer, src_buffer);
|
|
ret = bitblt_run(ge, blt);
|
|
if (ret < 0) {
|
|
LOGE("bitblt_run failed\n");
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void dither_set(struct ge_bitblt *blt, struct ge_buf *src_buffer, struct ge_buf *dst_buffer, int dith_en)
|
|
{
|
|
memset(blt, 0, sizeof(struct ge_bitblt));
|
|
|
|
memcpy(&blt->src_buf, &src_buffer->buf, sizeof(struct mpp_buf));
|
|
blt->src_buf.crop_en = 0;
|
|
|
|
memcpy(&blt->dst_buf, &dst_buffer->buf, sizeof(struct mpp_buf));
|
|
blt->dst_buf.crop_en = 0;
|
|
|
|
blt->ctrl.dither_en = dith_en;
|
|
}
|
|
|
|
static int dither_run(struct mpp_ge *ge, struct ge_bitblt *blt,
|
|
struct ge_buf *src_buffer, struct ge_buf *dst_buffer, int dith_en)
|
|
{
|
|
int ret = -1;
|
|
|
|
dither_set(blt, src_buffer, dst_buffer, dith_en);
|
|
ret = bitblt_run(ge, blt);
|
|
if (ret < 0) {
|
|
LOGE("bitblt_run failed\n");
|
|
return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void ge_dither_test(int argc, char **argv)
|
|
{
|
|
int ret = -1;
|
|
int dither_on = 0;
|
|
int src_format = 0;
|
|
int dst_format = 0;
|
|
|
|
int bmp_fd = -1;
|
|
enum mpp_pixel_format bmp_fmt = 0;
|
|
struct mpp_ge *ge = NULL;
|
|
struct ge_bitblt blt = {0};
|
|
struct ge_fb_info *fb_info = NULL;
|
|
struct ge_buf *bmp_buffer = NULL;
|
|
struct ge_buf *src_buffer = NULL;
|
|
struct ge_buf *dst_buffer = NULL;
|
|
struct bmp_header bmp_head = {0};
|
|
|
|
const char sopts[] = "uhs:d:o:i:";
|
|
const struct option lopts[] = {
|
|
{"usage", no_argument, NULL, 'u'},
|
|
{"help", no_argument, NULL, 'h'},
|
|
{"src_input" , required_argument, NULL, 'i'},
|
|
{"src_format", required_argument, NULL, 's'},
|
|
{"dst_format", required_argument, NULL, 'd'},
|
|
{"dither_on", required_argument, NULL, 'o'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
src_format = str_to_format("argb8888");
|
|
dst_format = str_to_format("argb4444");
|
|
optind = 0;
|
|
while ((ret = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
|
|
switch (ret) {
|
|
case 'i':
|
|
strncpy(g_src_input, optarg, sizeof(g_src_input) - 1);
|
|
break;
|
|
case 's':
|
|
src_format = str_to_format(optarg);
|
|
if (src_format < 0) {
|
|
printf("src format set error, please set against\n");
|
|
return;
|
|
}
|
|
break;
|
|
case 'd':
|
|
dst_format = str_to_format(optarg);
|
|
if (dst_format < 0) {
|
|
printf("dst format set error, please set against\n");
|
|
return;
|
|
}
|
|
break;
|
|
case 'o':
|
|
dither_on = str2int(optarg);
|
|
if ((dither_on > 1) || (dither_on < 0)) {
|
|
LOGE("dither switch set error, please set against\n");
|
|
return;
|
|
}
|
|
break;
|
|
case 'u':
|
|
usage(argv[0]);
|
|
return;
|
|
case 'h':
|
|
help();
|
|
return;
|
|
default:
|
|
LOGE("Invalid parameter: %#x\n", ret);
|
|
return;
|
|
}
|
|
}
|
|
|
|
ge = mpp_ge_open();
|
|
if (!ge) {
|
|
LOGE("open ge device error\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
fb_info = fb_open();
|
|
|
|
bmp_fd = bmp_open(g_src_input, &bmp_head);
|
|
if (bmp_fd < 0) {
|
|
LOGE("open bmp error, path = %s\n", g_src_input);
|
|
goto EXIT;
|
|
}
|
|
|
|
bmp_fmt = bmp_get_fmt(&bmp_head);
|
|
bmp_buffer = ge_buf_malloc(bmp_head.width, abs(bmp_head.height), bmp_fmt);
|
|
if (bmp_buffer == NULL) {
|
|
LOGE("malloc bmp_buffer error\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
src_buffer = ge_buf_malloc(bmp_head.width, abs(bmp_head.height), src_format);
|
|
if (src_buffer == NULL) {
|
|
LOGE("malloc src_buffer error\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
dst_buffer = ge_buf_malloc(bmp_head.width, abs(bmp_head.height), dst_format);
|
|
if (dst_buffer == NULL) {
|
|
LOGE("malloc dst_buffer error\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
ret = bmp_read(bmp_fd, (void *)((uintptr_t)bmp_buffer->buf.phy_addr[0]), &bmp_head);
|
|
if (ret < 0) {
|
|
LOGE("bmp_read error\n");
|
|
goto EXIT;
|
|
}
|
|
ge_buf_clean_dcache(bmp_buffer);
|
|
|
|
/* The ge operation here does not involve the CPU and does not required cleaning the dcache */
|
|
ret = bmp_to_src_run(ge, &blt, bmp_buffer, src_buffer);
|
|
if (ret < 0) {
|
|
LOGE("bmp_to_src_run failed\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
ret = display(ge, &blt, fb_info, src_buffer, SRC_DISP_REGION);
|
|
if (ret < 0) {
|
|
LOGE("display failed\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
ret = dither_run(ge, &blt, src_buffer, dst_buffer, dither_on);
|
|
if (ret < 0) {
|
|
LOGE("dither_run failed\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
ret = display(ge, &blt, fb_info, dst_buffer, DST_DISP_REGION);
|
|
if (ret < 0) {
|
|
LOGE("display failed\n");
|
|
goto EXIT;
|
|
}
|
|
fb_start_and_wait(fb_info);
|
|
fb_swap_frame(fb_info);
|
|
|
|
printf("ge dither test success\n");
|
|
EXIT:
|
|
if (bmp_fd > 0)
|
|
bmp_close(bmp_fd);
|
|
|
|
if (ge)
|
|
mpp_ge_close(ge);
|
|
|
|
if (fb_info)
|
|
fb_close(fb_info);
|
|
|
|
if (bmp_buffer)
|
|
ge_buf_free(bmp_buffer);
|
|
|
|
if (src_buffer)
|
|
ge_buf_free(src_buffer);
|
|
|
|
if (dst_buffer)
|
|
ge_buf_free(dst_buffer);
|
|
}
|
|
MSH_CMD_EXPORT_ALIAS(ge_dither_test, ge_dither, ge dithe test);
|