322 lines
11 KiB
C
322 lines
11 KiB
C
|
|
#include "typedef.h"
|
|
#include "rect.h"
|
|
#include "res/resfile.h"
|
|
|
|
#include "dbi.h"
|
|
#include "jlgpu_math.h" // matrix
|
|
#include "jlgpu_driver.h" // gpu driver
|
|
#include "ui_resource.h" // JL UI resource
|
|
#include "ui_expand/ui_expand.h" // macro defined
|
|
|
|
#include "gpu_port.h" // module head file
|
|
#include "gpu_draw.h" // custom draw head file
|
|
|
|
#include "ui_core.h"
|
|
#include "ui_measure.h"
|
|
|
|
#include "ui/lcd/lcd_drive.h"
|
|
#include "res/mem_var.h"
|
|
#include "football.h"
|
|
|
|
#include "gpu_demo.h"
|
|
#include "jljpeg_decode.h"
|
|
|
|
#include <math.h>
|
|
#if defined JPEG_DEMO_ENABLE && JPEG_DEMO_ENABLE
|
|
//===============================================================================================//
|
|
// 从文件解码jpeg demo
|
|
// 双链表解码jpeg参考 ui_platform.c \ gpu_task.c 相关流程
|
|
//===============================================================================================//
|
|
|
|
|
|
#define JPEG_FILE_PATH "storage/res_nor_mode/C/demo/jpg_test.jpg"
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief jlui_draw_jpeg_cb jpeg绘图回调
|
|
*
|
|
* @param id 0
|
|
* @param dst_buf 屏显buffer
|
|
* @param dst_r 屏显buffer rect
|
|
* @param src_r 图片/控件尺寸
|
|
* @param bytes_per_pixel 格式
|
|
* @param priv jpeg句柄
|
|
* @param matrix 变换矩阵
|
|
*/
|
|
/* ------------------------------------------------------------------------------------*/
|
|
static void jlui_draw_jpeg_cb(int id, u8 *dst_buf, struct rect *dst_r, struct rect *src_r, u8 bytes_per_pixel, void *priv, void *matrix)
|
|
{
|
|
|
|
if ((dst_r->width != lcd_get_screen_width()) && (dst_r->width + dst_r->left != lcd_get_screen_width())) {
|
|
//不支持局部刷新
|
|
return;
|
|
}
|
|
jdec_opj *opj = (jdec_opj *)priv; //jpeg解码句柄
|
|
opj->matrix = matrix; //获取变换矩阵
|
|
//计算缩放系数
|
|
float ratio_w = 1.0;
|
|
float ratio_h = 1.0;
|
|
if (opj->matrix) {
|
|
gpu_matrix_t *m = matrix;
|
|
ratio_w = m->m[0][0];//
|
|
ratio_h = m->m[1][1];//
|
|
/* printf("ratio_w: %f, ratio_h: %f\n", ratio_w, ratio_h); */
|
|
}
|
|
|
|
/* 计算变换后图片的输出区域 */
|
|
struct rect jpeg_draw_src;
|
|
memcpy(&jpeg_draw_src, src_r, sizeof(struct rect));
|
|
//放大时为中心放大
|
|
int center_y = src_r->top + src_r->height / 2;
|
|
jpeg_draw_src.height = opj->height / ratio_h;
|
|
jpeg_draw_src.top = center_y - jpeg_draw_src.height / 2;
|
|
int center_x = src_r->left + src_r->width / 2;
|
|
jpeg_draw_src.width = opj->width / ratio_w;
|
|
jpeg_draw_src.left = center_x - jpeg_draw_src.width / 2;
|
|
/* DUMP_RECT(__func__, __LINE__, "dst_r", dst_r); //推屏buf */
|
|
/* DUMP_RECT(__func__, __LINE__, "src_r", src_r); //jpeg显示区域 */
|
|
/* DUMP_RECT(__func__, __LINE__, "jpeg_draw_src", &jpeg_draw_src); //jpeg缩放后区域 */
|
|
|
|
/* 计算图片输出和推屏Buf的重叠区域 */
|
|
struct rect cover_r_t;
|
|
if (!get_rect_cover(dst_r, src_r, &cover_r_t)) {
|
|
return;
|
|
}
|
|
//计算缩放后的区域*以推屏区域、jpeg缩放区域、控件显示区域的交集作为最终输出,放大时受控件尺寸限制会变成中心放大
|
|
struct rect cover_r;
|
|
get_rect_cover(&cover_r_t, &jpeg_draw_src, &cover_r);
|
|
/* DUMP_RECT(__func__, __LINE__, "cover_r", &cover_r); //重叠区域 */
|
|
//计算jpeg解码的区域
|
|
int draw_top = cover_r.top - jpeg_draw_src.top; //绘制的top
|
|
int draw_btm = cover_r.height + draw_top; //绘制的bottom
|
|
int draw_h = cover_r.height; //绘制高度
|
|
/* int dec_top = draw_top * ratio_h; //需要解码的top */
|
|
/* int dec_btm = ceilf((float)draw_btm * ratio_h); //需要解码的高度,这里需要向上取 */
|
|
/* int dec_h = dec_btm - dec_top; //解码高度 */
|
|
int max_dec_height = (opj->msy << 3) / ratio_h; //一个mcu分块缩放后可以有效绘制的行数
|
|
int sub_top = 0;
|
|
int sub_height = (draw_h > max_dec_height) ? max_dec_height : draw_h;
|
|
//按mcu快缩放后的有效高度进行分行处理
|
|
while (sub_top + draw_top < draw_btm) {
|
|
int dec_sub_top = (draw_top + sub_top) * ratio_h;
|
|
int dec_sub_btm = ceilf((float)(draw_top + sub_top + sub_height) * ratio_h);
|
|
int dec_sub_h = dec_sub_btm - dec_sub_top;
|
|
/* printf("%s draw(%d %d) dec(%d %d)%d maxdec%d sub(%d %d) dec_sub(%d %d)", */
|
|
/* __func__, draw_top, draw_btm, dec_top, dec_btm, dec_h, max_dec_height, sub_top, sub_height, dec_sub_top, dec_sub_btm); */
|
|
struct rect jpeg_dec_r; /*jpeg解码区域*/
|
|
/* jpeg_dec_r.left = (cover_r.left - src_r->left) * ratio_w; */
|
|
jpeg_dec_r.left = (cover_r.left - jpeg_draw_src.left) * ratio_w;
|
|
jpeg_dec_r.top = dec_sub_top;
|
|
jpeg_dec_r.width = cover_r.width * ratio_w;
|
|
jpeg_dec_r.height = dec_sub_h;
|
|
struct rect block_r; /*缩放后显示的区域*/
|
|
block_r.top = cover_r.top + sub_top;
|
|
block_r.height = sub_height;
|
|
block_r.left = dst_r->left;
|
|
block_r.width = dst_r->width;
|
|
/* DUMP_RECT(__func__, __LINE__, "block_r", &block_r); */
|
|
/* DUMP_RECT(__func__, __LINE__, "jpeg_dec_r", &jpeg_dec_r); */
|
|
u8 *disp_buf = dst_buf + (block_r.top - dst_r->top) * 2 * lcd_get_screen_width();
|
|
/*启动解码*/
|
|
jljpeg_decode_start(opj, &jpeg_draw_src, &jpeg_dec_r, &cover_r, &block_r, disp_buf);
|
|
sub_top += sub_height;
|
|
sub_height = (sub_top + sub_height + draw_top < draw_btm) ? max_dec_height : draw_btm - draw_top - sub_top;
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief jlui_jpeg_infunc jpeg位流输入
|
|
*
|
|
* @param opj 句柄
|
|
* @param buf 位流buf
|
|
* @param len 预获取长度
|
|
*
|
|
* @return 实际数据长度
|
|
*/
|
|
/* ------------------------------------------------------------------------------------*/
|
|
|
|
static u32 jlui_jpeg_infunc(struct _jdec_opj *opj, u8 *buf, u32 len)
|
|
{
|
|
u32 rets;
|
|
__asm__ volatile("%0 = rets":"=r"(rets));
|
|
printf("%s jpeg_info:%x %x buf:%x rets:0x%x\n", __func__, (int)opj, (int)opj->device, (int)buf, rets);
|
|
if (buf) {
|
|
FILE *fp = (FILE *)opj->device;
|
|
fseek(fp, opj->curr_offset, SEEK_SET);
|
|
return fread(buf, len, 1, fp);
|
|
} else {
|
|
return len;
|
|
}
|
|
}
|
|
/* ------------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief jlui_free_jpeg_res_cb 解码资源释放回调,由gpu task调用
|
|
*
|
|
* @param p
|
|
*/
|
|
/* ------------------------------------------------------------------------------------*/
|
|
static void __jlui_free_jpeg_res_cb(void *p)
|
|
{
|
|
printf("%s 0x%x", __func__, (u32)p);
|
|
jdec_opj *opj = (jdec_opj *)p;
|
|
if (opj) {
|
|
/*释放图片资源*/
|
|
FILE *fp = (FILE *)opj->device;
|
|
fclose(fp);
|
|
/*释放底层*/
|
|
jljpeg_decode_release(opj, 0);
|
|
/*释放句柄*/
|
|
free(opj);
|
|
/*如果全局句柄与当前一致,释放,如果不一致说明已经切换为新的句柄,就不需再清*/
|
|
if (jljpeg_get_decode_hd() == opj) {
|
|
jljpeg_get_decode_hd_clr();
|
|
}
|
|
}
|
|
}
|
|
/* ------------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief jlui_draw_jpeg_cb_exit 任务销毁时调用,释放jpeg资源
|
|
*
|
|
* @param priv jpeg句柄
|
|
*
|
|
* @return
|
|
*/
|
|
/* ------------------------------------------------------------------------------------*/
|
|
static int jlui_draw_jpeg_cb_exit(void *draw_info, void *priv)
|
|
{
|
|
pJLGPUTaskDraw_t __draw_info = (pJLGPUTaskDraw_t)draw_info;
|
|
#if 0//双链表
|
|
/*使用双任务链推屏时,在息屏前或更新资源句柄前释放jpeg句柄,避免双链表冲突*/
|
|
__draw_info->priv = NULL;//由应用层释放
|
|
__draw_info->priv_len = 0;
|
|
#else//单链表可在exit释放资源
|
|
__jlui_free_jpeg_res_cb(__draw_info->priv);
|
|
__draw_info->priv = NULL;//由应用层释放
|
|
__draw_info->priv_len = 0;
|
|
#endif
|
|
return 0;
|
|
}
|
|
/* ------------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief jlui_draw_jpeg_cb_exit 任务销毁时调用,释放jpeg资源
|
|
*
|
|
* @param priv jpeg句柄
|
|
*
|
|
* @return
|
|
*/
|
|
/* ------------------------------------------------------------------------------------*/
|
|
static int jlui_draw_jpeg_res_free(jdec_opj *opj)
|
|
{
|
|
/* jdec_opj *opj = (jdec_opj *)jljpeg_get_decode_hd(); */
|
|
if (opj) {
|
|
#if 0//双链表
|
|
/*同步到gpu线程释放,避免gpu在使用jpeg资源*/
|
|
jlgpu_scheduler_async_free_jpeg_res(opj);
|
|
#else//单链表
|
|
//同一线程使用可以直接释放
|
|
__jlui_free_jpeg_res_cb(opj);
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
/* ------------------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief jlui_draw_jpeg_cb_enter 初始化jpeg资源
|
|
*
|
|
* @param priv jpeg句柄
|
|
*
|
|
* @return
|
|
*/
|
|
/* ------------------------------------------------------------------------------------*/
|
|
static int jlui_draw_jpeg_cb_enter(void *priv)
|
|
{
|
|
jdec_opj *opj = (jdec_opj *)priv;
|
|
/* printf("%s jpeg_info:%x %x", __func__, (int)opj, (int)opj->device); */
|
|
void *dev = opj->device;
|
|
/*初始化句柄*/
|
|
int ret = jljpeg_decode_init(opj);
|
|
if (!ret) {
|
|
/*解析资源*/
|
|
ret = jljpeg_img_info_get(opj, jlui_jpeg_infunc, dev);
|
|
ASSERT(!ret, "jpeg file notsupport err:%x", ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
void jpeg_demo_from_file(pJLGPUTaskHead_t head, int x, int y)
|
|
{
|
|
jlgpu_task_basic_param_init(GPU_TASK_DRAW, 0x1, 0);
|
|
task_param.format = GPU_FORMAT_RGB565;
|
|
|
|
jlgpu_get_win_rect(&task_param.area);
|
|
|
|
task_param.cb_func = jlui_draw_jpeg_cb;
|
|
task_param.cb_exit = jlui_draw_jpeg_cb_exit;
|
|
//判断jpeg句柄是否存在
|
|
jdec_opj *jpg_hd = jljpeg_get_decode_hd();
|
|
|
|
if (jpg_hd) {
|
|
struct flash_file_info *jpg_dev = (struct flash_file_info *)jpg_hd->device;
|
|
/* printf("%s hd:0x%x rec:0x%x new:0x%x",__func__,(u32)hd,jpg_dev->offset,task_param.info.offset); */
|
|
//比较是否为同一张图片
|
|
if (task_param.info.offset == jpg_dev->offset) {
|
|
task_param.priv = jpg_hd;
|
|
task_param.priv_len = sizeof(jdec_opj);
|
|
task_param.draw_en = 1;
|
|
} else {
|
|
jlui_draw_jpeg_res_free(jpg_hd);
|
|
goto __new_jpg_hd;
|
|
}
|
|
} else {
|
|
__new_jpg_hd:
|
|
task_param.priv = malloc(sizeof(jdec_opj));
|
|
task_param.priv_len = sizeof(jdec_opj);
|
|
|
|
task_param.draw_en = 1;
|
|
jpg_hd = task_param.priv;
|
|
FILE *fp = fopen(JPEG_FILE_PATH, "r");
|
|
jpg_hd->device = fp;
|
|
printf("%s dev:%x", __func__, (u32)jpg_hd->device);
|
|
if (jlui_draw_jpeg_cb_enter(jpg_hd)) {
|
|
jlui_draw_jpeg_res_free(jpg_hd);
|
|
return ;
|
|
}
|
|
}
|
|
task_param.draw.left = x;
|
|
task_param.draw.top = y;
|
|
task_param.draw.width = jpg_hd->width;
|
|
task_param.draw.height = jpg_hd->height;
|
|
|
|
jlgpu_update_task_by_id(head, task_param.task_id, task_param.element_id, &task_param);
|
|
|
|
}
|
|
|
|
void jpeg_demo_test(pJLGPUTaskHead_t head)
|
|
{
|
|
//参数化jpeg模块
|
|
jpeg_decode_module_init(NULL, NULL, jdec_to_jlgpu_texture_blend);
|
|
//创建jpeg任务
|
|
jpeg_demo_from_file(head, 20, 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|