This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
File diff suppressed because it is too large Load Diff
+462
View File
@@ -0,0 +1,462 @@
#include "typedef.h"
#include "rect.h"
#include "res/resfile.h"
#include "dbi.h"
#include "jlgpu_math.h"
#include "jlgpu_driver.h"
#include "ui_resource.h" // RES格式与GPU格式互转接口
#include "ui_expand/ui_expand.h" // 使用一些宏定义
#include "gpu_draw.h"
#include "gpu_port.h"
#include "ui_draw/ui_basic.h"
#include <math.h>
#include "jlui_app/ui_style.h"
#if (defined(CONFIG_UI_STYLE_JL_PUBLIC_MODLS_ENABLE) || defined(CONFIG_UI_STYLE_JL_CSC_PUBLIC_MODLS_ENABLE))
/* debug 打印配置 */
#define LOG_TAG_CONST JL_GPU
#define LOG_TAG "[JL GPU]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
extern int ui_disp_out_stride_get();
extern int lcd_get_screen_width();
extern int lcd_get_screen_height();
static void jlui_blend_by_gpu(u8 *mask_buf, struct rect *mask_r, u8 *disp_buf, struct rect *disp_r, int color);
static const struct gpu_blend_interface gpu_draw_interface = {
.gpu_blend = jlui_blend_by_gpu,
};
/* ------------------------------------------------------------------------------------*/
/**
* @brief jlui_blend_by_gpu gpu绘图
*
* @param mask_buf 非压缩A8数据(前景)
* @param mask_r A8数据绘制区域
* @param disp_buf 底图,一般是屏驱buf(后景)
* @param disp_r 底图区域
* @param color A8颜色,这里传565
*/
/* ------------------------------------------------------------------------------------*/
AT_UI_RAM
void jlui_blend_mask(u8 *mask_buf, struct rect *mask_r, u8 *disp_buf, struct rect *disp_r, struct rect *draw_r, u32 color, float ratio_w, float ratio_h, int in_format)
{
int r = ((color >> 11) & 0x1f) << 3;
int g = ((color >> 5) & 0x3f) << 2;
int b = ((color) & 0x1f) << 3;
/* printf("%s (%d %d %d %d) (%d %d %d %d) %x %x (%d %d %d)", __func__, */
/* mask_r->left, mask_r->top, mask_r->width, mask_r->height, */
/* disp_r->left, disp_r->top, disp_r->width, disp_r->height, */
/* (int)mask_buf, (int)disp_buf, r, g, b); */
gpu_out_params_t out_param = { 0 };
gpu_basic_params_t basic_param = { 0 };
gpu_transform_params_t transform_param = {0};
out_param.data = (uint8_t *)disp_buf;
out_param.win_x_min = disp_r->left;
out_param.win_x_max = disp_r->left + disp_r->width ;
out_param.win_y_min = disp_r->top;
out_param.win_y_max = disp_r->top + disp_r->height ;
out_param.stride = lcd_get_screen_width() * 2; //disp_r->width * 2;
out_param.format = GPU_FORMAT_RGB565;
/*********针对draw_r的区域超出屏幕区域的情况*****/
struct rect lcd_rect;
lcd_rect.left = 0;
lcd_rect.top = 0;
lcd_rect.width = lcd_get_screen_width();
lcd_rect.height = lcd_get_screen_height();
struct rect draw_rect;
get_rect_cover(&lcd_rect, draw_r, &draw_rect);
/************************************************/
/* basic_param.act_x_min = mask_r->left ; */
/* basic_param.act_x_max = mask_r->left + mask_r->width; */
/* basic_param.act_y_min = mask_r->top ; */
/* basic_param.act_y_max = mask_r->top + mask_r->height; */
basic_param.act_x_min = draw_rect.left ;
basic_param.act_x_max = draw_rect.left + draw_rect.width ;
basic_param.act_y_min = draw_rect.top ;
basic_param.act_y_max = draw_rect.top + draw_rect.height;
/* printf("basic:{%d %d %d %d}", basic_param.act_x_min, basic_param.act_x_max, basic_param.act_y_min, basic_param.act_y_max); */
basic_param.alpha = 255;
basic_param.red = r;
basic_param.green = g;
basic_param.blue = b;
basic_param.layer_en = 1;
basic_param.blend_mode = 1;
basic_param.global_alpha = 128; //范围:0-128
basic_param.premult = 0;
gpu_texture_params_t texture_param = { 0 };
texture_param.adr_mode = 1;
texture_param.data = mask_buf;
texture_param.format = in_format;
texture_param.compress_mode = 0;
texture_param.stride = (mask_r->width * gpu_get_format_bpp(in_format) + 7) / 8 ;
texture_param.compress_size = mask_r->width;
texture_param.big_end = 1;
float zoom_w = (float)1 / ratio_w;
float zoom_h = (float)1 / ratio_h;
gpu_matrix_t matrix;
gpu_matrix_set_identity(&matrix);
float tran_x = (float)draw_r->left;
float tran_y = (float)draw_r->top;
gpu_matrix_translate(&matrix, -tran_x, -tran_y);
gpu_matrix_scale(&matrix, zoom_w, zoom_h);
/* printf("%s %f %f %f %f\n", __func__, zoom_w, zoom_h, tran_x, tran_y); */
transform_param.M00 = matrix.m[0][0];
transform_param.M01 = matrix.m[0][1];
transform_param.M02 = matrix.m[0][2] - 0.5f * transform_param.M00 - 0.5f * transform_param.M01 + 0.5f;
transform_param.M10 = matrix.m[1][0];
transform_param.M11 = matrix.m[1][1];
transform_param.M12 = matrix.m[1][2] - 0.5f * transform_param.M10 - 0.5f * transform_param.M11 + 0.5f;
transform_param.fg_x_min = 0;
transform_param.fg_x_max = mask_r->width;
transform_param.fg_y_min = 0;
transform_param.fg_y_max = mask_r->height;
transform_param.sample_mode = 0;
transform_param.shift_sel = 6;
uint8_t mode = GPU_TEXTURE_AFFINE;
gpu_reset_all_regs(mode);
gpu_texture_affine(&basic_param, &texture_param, &transform_param);
gpu_set_out_layer(&out_param);
gpu_isr_sem_clr();
gpu_run();
gpu_wait_done();
/* printf("%s %d", __func__, __LINE__); */
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jlui_blend_by_gpu gpu绘图
*
* @param mask_buf 非压缩A8数据(前景)
* @param mask_r A8数据绘制区域
* @param disp_buf 底图,一般是屏驱buf(后景)
* @param disp_r 底图区域
* @param color A8颜色,这里传565
*/
/* ------------------------------------------------------------------------------------*/
extern const int JLUI_CUSTOM_DRAW_CACHE;
AT_UI_RAM
static void jlui_blend_by_gpu(u8 *mask_buf, struct rect *mask_r, u8 *disp_buf, struct rect *disp_r, int color)
{
if (JLUI_CUSTOM_DRAW_CACHE) {
/* memcpy(disp_buf, mask_buf, disp_r->width * disp_r->height); // 一定是A8格式,直接copy */
return;
}
u8 r = ((color >> 11) & 0x1f) << 3;
u8 g = ((color >> 5) & 0x3f) << 2;
u8 b = ((color) & 0x1f) << 3;
u8 alpha = ((u32)color) >> 24;
/* printf("%s (%d %d %d %d) (%d %d %d %d) %x %x (%d %d %d)", __func__, */
/* mask_r->left, mask_r->top, mask_r->width, mask_r->height, */
/* disp_r->left, disp_r->top, disp_r->width, disp_r->height, */
/* (int)mask_buf, (int)disp_buf, r, g, b); */
/* put_buf(mask_buf,320*mask_r->height); */
gpu_out_params_t out_param = { 0 };
gpu_basic_params_t basic_param = { 0 };
out_param.data = (uint8_t *)disp_buf;
out_param.win_x_min = 0;
out_param.win_x_max = disp_r->width;
out_param.win_y_min = 0;
out_param.win_y_max = disp_r->height;
out_param.stride = ui_disp_out_stride_get(); // disp_r->width*2;//lcd_get_screen_width() * 2;
out_param.format = GPU_FORMAT_RGB565;
basic_param.act_x_min = mask_r->left;
basic_param.act_x_max = mask_r->left + mask_r->width;
basic_param.act_y_min = mask_r->top;
basic_param.act_y_max = mask_r->top + mask_r->height;
basic_param.alpha = 255;
basic_param.red = r;
basic_param.green = g;
basic_param.blue = b;
basic_param.layer_en = 1;
basic_param.blend_mode = 1;
basic_param.global_alpha = alpha * 128 / 255; //范围:0-128
#if 0
uint8_t mode = GPU_TEXTURE;
gpu_texture_params_t texture_param = { 0 };
texture_param.adr_mode = 1;
texture_param.data = mask_buf;
texture_param.format = GPU_FORMAT_A8;
texture_param.compress_mode = 0;
texture_param.stride = (mask_r->width * gpu_get_format_bpp(GPU_FORMAT_A8) + 7) / 8 ;
texture_param.compress_size = mask_r->width;
texture_param.big_end = 1;
gpu_reset_all_regs(mode);
gpu_texture(&basic_param, &texture_param);
gpu_set_out_layer(&out_param);
gpu_isr_sem_clr();
gpu_run();
gpu_wait_done();
#else
uint8_t mode = GPU_FILL_MASK;
gpu_mask_params_t mask_param = {0};
mask_param.data = mask_buf;
mask_param.mask_big_end = 0;
mask_param.mask_format = GPU_MASK_FORMAT_A8;
mask_param.mask_x_min = 0;
mask_param.mask_x_max = mask_r->width;
mask_param.mask_y_min = 0;
mask_param.mask_y_max = mask_r->height;
mask_param.stride = (mask_r->width * gpu_get_format_bpp(GPU_FORMAT_A8) + 7) / 8 ;
gpu_reset_all_regs(mode);
gpu_fill_mask(&basic_param, &mask_param);
gpu_set_out_layer(&out_param);
gpu_isr_sem_clr();
gpu_run();
gpu_wait_done();
#endif
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jdec_to_jlgpu_texture_blend 硬件 GPU2D YUV422 格式 UYVY 转 RGB565
*
* @param dst_buf 输出buffer,一般为推屏buffer
* @param dst_rect 输出buffer位置
* @param src_buf jpeg图像数据
* @param src_rect 图像数据位置(相对于jpeg)
* @param draw_rect 绘制区域
* @param stride 行步进
* @param format 预留
* @param p 私有句柄,预留给变换传参
* @return 0 linebuf已完全绘制 1linebuf未完全绘制
* @return linebuf使用后剩余行数
*/
/* ------------------------------------------------------------------------------------*/
#define GPU_OFFSET 800
void dump_matrix(gpu_matrix_t *matrix);
int jdec_to_jlgpu_texture_blend(u8 *dst_buf, struct rect *dst_rect, u8 *src_buf, struct rect *src_rect, struct rect *draw_rect, int src_stride, int format, void *p, int line_surpule, struct rect *cover_rect)
{
//缩放矩阵
gpu_matrix_t tmp_matrix;
gpu_matrix_t *matrix = NULL;
if (p) {
matrix = (gpu_matrix_t *)&tmp_matrix;
memcpy(matrix, p, sizeof(gpu_matrix_t));
} else {
matrix = (gpu_matrix_t *)&tmp_matrix;
gpu_matrix_set_identity(matrix);
}
//缩放系数
float ratio_w = 1.0f, ratio_h = 1.0f; //倒数
if (matrix) {
ratio_w = matrix->m[0][0];
ratio_h = matrix->m[1][1];
}
//区域计算
/* DUMP_RECT(__func__, __LINE__, "dst_rect", dst_rect); //disp_buf区域 */
/* DUMP_RECT(__func__, __LINE__, "src_rect", src_rect); //jpeg解码区域(缩放前,局部) */
/* DUMP_RECT(__func__, __LINE__, "draw_rect", draw_rect); //jpeg显示区域(缩放后,局部) */
/* DUMP_RECT(__func__, __LINE__, "cover_rect", cover_rect); //jpeg限制区域 (全局) */
//计算缩放后的尺寸
struct rect jpeg_dec_scale_r;
jpeg_dec_scale_r.left = src_rect->left / ratio_w;
jpeg_dec_scale_r.top = ((float)src_rect->top / ratio_h);
jpeg_dec_scale_r.width = src_rect->width / ratio_w;
jpeg_dec_scale_r.height = (int)(src_rect->top + src_rect->height) / ratio_h - jpeg_dec_scale_r.top;
/* DUMP_RECT(__func__, __LINE__, "jpeg_dec_scale_r", (struct rect *)(&jpeg_dec_scale_r)); //缩放后的区域 */
//偏移到显示位置
struct rect jpeg_dec_draw;
jpeg_dec_draw.left = draw_rect->left + jpeg_dec_scale_r.left;
jpeg_dec_draw.top = draw_rect->top + jpeg_dec_scale_r.top;
jpeg_dec_draw.width = jpeg_dec_scale_r.width;
jpeg_dec_draw.height = jpeg_dec_scale_r.height;
/* DUMP_RECT(__func__, __LINE__, "jpeg_dec_draw", (struct rect *)(&jpeg_dec_draw)); //缩放后在屏幕显示的区域 */
//与推屏区域取交集
struct rect jpeg_dec_draw_cover_t;
if (!get_rect_cover(dst_rect, &jpeg_dec_draw, &jpeg_dec_draw_cover_t)) {
return 0 ;
}
//对显示区域取交集
struct rect jpeg_dec_draw_cover;
get_rect_cover(&jpeg_dec_draw_cover_t, cover_rect, &jpeg_dec_draw_cover);
/* DUMP_RECT(__func__, (jpeg_dec_draw_cover.top + jpeg_dec_draw_cover.height), "jpeg_dec_draw_cover", (struct rect *)(&jpeg_dec_draw_cover)); //与推屏buf的交集 */
//输出配置
int out_stride = ui_disp_out_stride_get(); //RGB565
gpu_out_params_t out_param = {0};
gpu_basic_params_t basic_param = {0};
gpu_texture_params_t texture_param = {0};
gpu_transform_params_t transform_param = {0};
uint8_t adr_mode = 1;
uint8_t blend_mode = GPU_BLEND_SRC;
uint8_t mode = GPU_TEXTURE;
if (matrix) {//缩放
mode = GPU_TEXTURE_AFFINE;
out_param.data = (uint8_t *)dst_buf;
out_param.win_x_min = GPU_OFFSET + dst_rect->left;
out_param.win_x_max = GPU_OFFSET + dst_rect->left + dst_rect->width;
out_param.win_y_min = GPU_OFFSET + dst_rect->top;
out_param.win_y_max = GPU_OFFSET + dst_rect->top + dst_rect->height;
} else {
out_param.data = (uint8_t *)dst_buf + (jpeg_dec_draw_cover.top - dst_rect->top) * out_stride;
out_param.win_x_min = GPU_OFFSET + dst_rect->left;
out_param.win_x_max = GPU_OFFSET + dst_rect->left + dst_rect->width;
out_param.win_y_min = GPU_OFFSET + jpeg_dec_draw_cover.top;
out_param.win_y_max = GPU_OFFSET + jpeg_dec_draw_cover.top + jpeg_dec_draw_cover.height;
}
/* printf("@@@ win [%d, %d, %d, %d] h:%d \n", out_param.win_x_min, out_param.win_y_min, out_param.win_x_max - out_param.win_x_min, out_param.win_y_max - out_param.win_y_min, jpeg_dec_draw_cover.height); */
out_param.stride = out_stride;
out_param.format = GPU_FORMAT_RGB565;
if (matrix) {
basic_param.act_x_min = GPU_OFFSET + jpeg_dec_draw_cover.left;
basic_param.act_x_max = GPU_OFFSET + jpeg_dec_draw_cover.left + jpeg_dec_draw_cover.width;
basic_param.act_y_min = GPU_OFFSET + jpeg_dec_draw_cover.top;
basic_param.act_y_max = GPU_OFFSET + jpeg_dec_draw_cover.top + jpeg_dec_draw_cover.height;
} else {
basic_param.act_x_min = GPU_OFFSET + draw_rect->left;
basic_param.act_x_max = GPU_OFFSET + draw_rect->left + draw_rect->width;
basic_param.act_y_min = GPU_OFFSET + jpeg_dec_draw.top;
basic_param.act_y_max = GPU_OFFSET + jpeg_dec_draw.top + jpeg_dec_draw.height;
}
/* printf("@@@ box [%d, %d, %d, %d]\n", basic_param.act_x_min, basic_param.act_y_min, basic_param.act_x_max - basic_param.act_x_min, basic_param.act_y_max - basic_param.act_y_min); */
basic_param.global_alpha = 128;
basic_param.blend_mode = blend_mode;
basic_param.premult = 0;
basic_param.layer_en = 1;
basic_param.ext_mode = 1;
texture_param.adr_mode = adr_mode;
texture_param.rbs = 0; // must 0; YUV422 => UYVY
texture_param.data = (uint8_t *)src_buf ;
texture_param.format = GPU_FORMAT_YUV422_BT601;
texture_param.compress_mode = 0;
texture_param.stride = src_stride;
texture_param.compress_size = src_rect->width;
gpu_reset_all_regs(mode);
if (matrix) {
gpu_matrix_set_identity(matrix);
gpu_matrix_translate(matrix, -GPU_OFFSET, -GPU_OFFSET);
struct rect real_scale_r;
memcpy(&real_scale_r, &jpeg_dec_draw, sizeof(struct rect));
real_scale_r.height = (int)(src_rect->height) / ratio_h;
struct rect real_scale_cover_t;
get_rect_cover(dst_rect, &real_scale_r, &real_scale_cover_t);
struct rect real_scale_cover;
get_rect_cover(&real_scale_cover_t, cover_rect, &real_scale_cover);
if ((jpeg_dec_draw_cover.top + jpeg_dec_draw_cover.height) == (real_scale_cover.top + real_scale_cover.height)) {
gpu_matrix_translate(matrix, -draw_rect->left, - jpeg_dec_draw.top);
} else {
//浮点补偿
gpu_matrix_translate(matrix, -draw_rect->left, -(((float)src_rect->top / ratio_h) + draw_rect->top));
}
/* printf("%s matrix_offset:%f %f",__func__,matrix->m[0][2],matrix->m[1][2]); */
gpu_matrix_scale(matrix, ratio_w, ratio_h);
transform_param.M00 = matrix->m[0][0];
transform_param.M01 = matrix->m[0][1];
transform_param.M02 = matrix->m[0][2] - 0.5f * transform_param.M00 - 0.5f * transform_param.M01 + 0.5f;
transform_param.M10 = matrix->m[1][0];
transform_param.M11 = matrix->m[1][1];
transform_param.M12 = matrix->m[1][2]/* - 0.5f * transform_param.M10 - 0.5f * transform_param.M11 + 0.5f*/;
transform_param.fg_x_min = 0;
transform_param.fg_x_max = src_rect->width;
transform_param.fg_y_min = 0;
transform_param.fg_y_max = src_rect->height;
transform_param.sample_mode = 0;
transform_param.shift_sel = 6;
gpu_texture_affine(&basic_param, &texture_param, &transform_param);
} else {
gpu_texture(&basic_param, &texture_param);
}
gpu_set_out_layer(&out_param);
gpu_isr_sem_clr();
gpu_run();
gpu_wait_done();
return 0;
}
void jlui_argb8565_to_rgb565(u8 *out_buf, struct rect *out_r, u8 *in_buf, struct rect *in_r)
{
gpu_out_params_t out_param = { 0 };
gpu_basic_params_t basic_param = { 0 };
gpu_transform_params_t transform_param = {0};
//out info
out_param.data = (uint8_t *)out_buf;
out_param.win_x_min = 0;
out_param.win_x_max = out_r->width ;
out_param.win_y_min = 0;
out_param.win_y_max = out_r->height ;
out_param.format = GPU_FORMAT_RGB565;
out_param.stride = (out_r->width * gpu_get_format_bpp(out_param.format) + 7) / 8;
//in info
basic_param.act_x_min = 0;
basic_param.act_x_max = in_r->width;
basic_param.act_y_min = 0;
basic_param.act_y_max = in_r->height;
basic_param.alpha = 0xff;
basic_param.layer_en = 1;
basic_param.blend_mode = 1;
basic_param.global_alpha = 128; //范围:0-128
basic_param.premult = 1;
//in texture
gpu_texture_params_t texture_param = { 0 };
texture_param.adr_mode = 1;
texture_param.data = in_buf;
texture_param.format = GPU_FORMAT_ARGB8565;
texture_param.compress_mode = 0;
texture_param.stride = (in_r->width * gpu_get_format_bpp(texture_param.format) + 7) / 8 ;
texture_param.compress_size = in_r->width;
uint8_t mode = GPU_TEXTURE;
gpu_reset_all_regs(mode);
gpu_texture(&basic_param, &texture_param);
gpu_set_out_layer(&out_param);
gpu_isr_sem_clr();
gpu_run();
gpu_wait_done();
}
void jlui_gpu_blend_init()
{
gpu_blend_init((struct gpu_blend_interface *)&gpu_draw_interface);
}
#endif
@@ -0,0 +1,9 @@
#ifndef __PUBLIC_GPU_DRAW_H__
#define __PUBLIC_GPU_DRAW_H__
void jlui_gpu_blend_init();
int jdec_to_jlgpu_texture_blend(u8 *dst_buf, struct rect *dst_rect, u8 *src_buf, struct rect *src_rect, struct rect *draw_rect, int src_stride, int format, void *p, int line_surpule, struct rect *cover);
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,49 @@
#ifndef __PUBLIC_GPU_TASK_H__
#define __PUBLIC_GPU_TASK_H__
/* ------------------------------------------------------------------------------------*/
/**
* @brief GPU 任务名
*/
/* ------------------------------------------------------------------------------------*/
#define GPU_TASK_NAME "gpu"
/* ------------------------------------------------------------------------------------*/
/**
* @brief GPU任务消息类型
*/
/* ------------------------------------------------------------------------------------*/
typedef enum {
GPU_MSG_OTHER,
GPU_MSG_DRAW,
GPU_MSG_DUMP,
GPU_MSG_DRAW_LIST,
} gpu_task_msg_t;
/* ------------------------------------------------------------------------------------*/
/**
* @brief GPU刷新方式标志
*/
/* ------------------------------------------------------------------------------------*/
typedef enum {
GPU_SYNC_REDRAW, // 同步/串行刷新
GPU_ASYN_REDRAW, // 异步/并行刷新
} gpu_redraw_mode_t;
int jlgpu_scheduler_async_free_buf(void *p);
void jlgpu_scheduler_set_redraw_mode(struct draw_context *dc, gpu_redraw_mode_t mode);
void *jlgpu_scheduler_create_mult_task_list(struct draw_context *dc);
void jlgpu_scheduler_delete_mult_task_list(struct draw_context *dc);
void *jlgpu_scheduler_draw_mult_task_list(struct draw_context *dc);
void jlgpu_scheduler_init(void *(*malloc)(int, u32, u32), void (*free)(void *, u32, u32), u16 lcd_width, u16 lcd_height);
void jlgpu_scheduler_free();
int jlgpu_scheduler_wait_sync();
int jlgpu_scheduler_async_free_jpeg_res(void *p);
int jlgpu_scheduler_get_redraw_mode();
#endif
@@ -0,0 +1,989 @@
#include "system/includes.h"
#include "app_config.h"
#include "jljpeg_decode.h"
#include "res/resfile.h"
#include "ui_core.h"
#include "jlgpu_math.h" // matrix
#include "jlgpu_driver.h" // gpu 驱动
#include "gpu_port.h" // GPU 接口,依赖于 jlgpu_driver.h
#include "gpu_task.h"
#include <math.h>
#include "ui/lcd/lcd_drive.h" // lcd 驱动
#define LOG_TAG_CONST JPEG
#define LOG_TAG "[JPEG]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_WARN_ENABLE
#define LOG_CHAR_ENABLE
#include "debug.h"
struct jpeg_hd_manager {
struct list_head entry;
jdec_opj *opj;
u32 check;
u32 vaild;
u32 task_id;
u32 elm_id;
u8 file_flag;
};
struct jpeg_priv {
u32 task_id;
u32 elm_id;
};
struct jpeg_hd_manager jpg_hd_manager_info;
#define __this (&jpg_hd_manager_info)
spinlock_t lock;
#define ENTER_CRITICAL() spin_lock(&lock)
#define EXIT_CRITICAL() spin_unlock(&lock)
#define UI_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);}
#define UI_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);}
int jpeg_module_opj_free_file_hd(FILE *fp);
int jlgpu_scheduler_async_free_jpeg_res(void *p);
int jpeg_module_opj_release_async(void *jpg);
void *psram_cache_2_nocache(void *p);
u32 jlui_jpeg_infunc_bits_stream(struct _jdec_opj *opj, u8 *buf, u32 len);
extern void psram_flush_cache(void *begin, u32 len);
extern const u8 norflash_ext_sfc_en;//给gpu判断互斥
extern void norflash_espi_mutex_enter();
extern void norflash_espi_mutex_exit();
extern u32 ps_ram_size[];
static volatile const u32 psram_size = (u32)ps_ram_size;
#define IS_SFC1_ADDR(addr) (!psram_size && (memory_in_flash(addr)))
#define DUMP_RECT(func, line, name, rect) \
printf("[RECT] %s() %d, %s [%d, %d, %d, %d]\n", func, line, name, (rect)->left, (rect)->top, (rect)->width, (rect)->height)
//======================================================================//
// jpeg链表管理
// 支持多jpeg显示,注意
// 1. 多jpeg水平方向无交叉时,效率不影响(即垂直排列)
// 2. 需要全屏刷新
// 3. 不带psram时不支持变换
// 4. 注意ram消耗
//======================================================================//
void *jpeg_hd_create_priv(u32 task_id, u32 elm_id)
{
struct jpeg_priv *priv = (struct jpeg_priv *)jpeg_malloc(sizeof(struct jpeg_priv));
priv->task_id = task_id;
priv->elm_id = elm_id;
return (void *)priv;
}
int jpeg_hd_get_priv_len()
{
return sizeof(struct jpeg_priv);
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_check 查询是否存在jpeg句柄
*
* @param check
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static void *jpeg_hd_manager_check(u32 check)
{
struct jpeg_hd_manager *p;
struct jpeg_hd_manager *rp = NULL;
ENTER_CRITICAL();
list_for_each_entry(p, &__this->entry, entry) {
if (p->check == check) {
rp = p;
break;
}
}
EXIT_CRITICAL();
if (rp) {
log_debug("%s hd:0x%x opj:0x%x check:0x%x", __func__, (u32)rp, (u32)rp->opj, check);
} else {
log_debug("%s check:0x%x", __func__, check);
}
return (void *)rp;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_find_by_opj 判断句柄是否存在
*
* @param opj
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static void *jpeg_hd_manager_find_by_opj(void *opj)
{
struct jpeg_hd_manager *p;
struct jpeg_hd_manager *rp = NULL;
ENTER_CRITICAL();
list_for_each_entry(p, &__this->entry, entry) {
if (p->opj == opj) {
rp = p;
break;
}
}
EXIT_CRITICAL();
if (rp) {
log_debug("%s hd:0x%x opj:0x%x check:0x%x", __func__, (u32)rp, (u32)rp->opj, (u32)opj);
} else {
log_debug("%s check:0x%x", __func__, (u32)opj);
}
return (void *)rp;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_find_by_id 通过id查找句柄
*
* @param task_id
* @param elm_id
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static void *jpeg_hd_manager_find_by_id(u32 task_id, u32 elm_id)
{
struct jpeg_hd_manager *p;
struct jpeg_hd_manager *rp = NULL;
ENTER_CRITICAL();
list_for_each_entry(p, &__this->entry, entry) {
if ((p->task_id == task_id)
&& (p->elm_id == elm_id)) {
rp = p;
break;
}
}
EXIT_CRITICAL();
if (rp) {
log_debug("%s hd:0x%x opj:0x%x task_id:0x%x elm_id:0x%x \n", __func__, (u32)rp, (u32)rp->opj, task_id, elm_id);
} else {
log_debug("%s task_id:0x%x elm_id:0x%x \n", __func__, task_id, elm_id);
}
return (void *)rp;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_add 添加jpeg句柄记录
*
* @param opj
* @param check
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static struct jpeg_hd_manager *jpeg_hd_manager_add(void *opj, u32 check)
{
struct jpeg_hd_manager *p = jpeg_malloc(sizeof(struct jpeg_hd_manager));
memset(p, 0, sizeof(struct jpeg_hd_manager));
p->opj = (jdec_opj *)opj;
p->check = check;
p->vaild = 0;
log_debug("%s hd:0x%x opj:0x%x check:0x%x", __func__, (u32)p, (u32)p->opj, check);
ENTER_CRITICAL();
list_add_tail(&p->entry, &__this->entry);
EXIT_CRITICAL();
return p;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_del 删除jpeg句柄记录
*
* @param opj
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static int jpeg_hd_manager_del(void *opj)
{
log_debug("%s opj:0x%x ", __func__, (u32)opj);
struct jpeg_hd_manager *p, *n;
ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &__this->entry, entry) {
if (p->opj == opj) {
list_del(&(p->entry));
if (p->file_flag) {
FILE *fp = (FILE *)(((int *)p->opj->device)[0]);
jpeg_module_opj_free_file_hd(fp);
}
jpeg_module_opj_release_async((void *)p->opj);
jpeg_free(p);
break;
}
}
EXIT_CRITICAL();
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_clr 清空所有jpeg句柄记录
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static int jpeg_hd_manager_clr()
{
log_debug("%s %d", __func__, __LINE__);
struct jpeg_hd_manager *p, *n;
ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &__this->entry, entry) {
list_del(&(p->entry));
if (p->file_flag) {
FILE *fp = (FILE *)(((int *)p->opj->device)[0]);
jpeg_module_opj_free_file_hd(fp);
}
jpeg_module_opj_release_async((void *)p->opj);
jpeg_free(p);
}
EXIT_CRITICAL();
log_debug("%s %d", __func__, __LINE__);
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_vaild_set 有效性设置
*
* @param opj
* @param vaild
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static int jpeg_hd_manager_vaild_set(void *opj, int vaild)
{
log_debug("%s opj:0x%x", __func__, (u32)opj);
struct jpeg_hd_manager *p, *n;
ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &__this->entry, entry) {
if (p->opj == opj) {
p->vaild = vaild;
log_debug("%s hd:0x%x opj:0x%x svaild:%d pvaild:0x%x", __func__, (u32)p, (u32)opj, vaild, p->vaild);
break;
}
}
EXIT_CRITICAL();
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_hd_manager_vaild_sub 有效性--
*
* @param opj
* @param vaild
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
static int jpeg_hd_manager_vaild_sub(void *opj)
{
log_debug("%s opj:0x%x", __func__, (u32)opj);
struct jpeg_hd_manager *p, *n;
ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &__this->entry, entry) {
if (p->opj == opj) {
if (p->vaild) {
p->vaild --;
}
log_debug("%s hd:0x%x opj:0x%x pvaild:0x%x", __func__, (u32)p, (u32)opj, p->vaild);
break;
}
}
EXIT_CRITICAL();
return 0;
}
//======================================================================//
// jpeg句柄管理
//======================================================================//
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_free_res_cb jpeg资源释放接口,gpu_task调用
*
* @param p
*/
/* ------------------------------------------------------------------------------------*/
void jpeg_module_free_res_cb(void *p)
{
jdec_opj *opj = (jdec_opj *)p;
if (opj) {
/*释放图片资源*/
jpeg_free(opj->device);
/*释放底层*/
jljpeg_decode_release(opj, 0);
jpeg_hd_manager_del(p);
/*释放句柄*/
jpeg_free(opj);
/*如果全局句柄与当前一致,释放,如果不一致说明已经切换为新的句柄,就不需再清*/
if (jljpeg_get_decode_hd() == opj) {
jljpeg_get_decode_hd_clr();
}
}
}
int jpeg_module_opj_free_file_hd(FILE *fp)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
printf("%s 0x%x [FILE]fp:0x%x", __func__, rets, (u32)fp);
int argv[3] = {0};
int retry = 3;
argv[0] = (int)fclose;
argv[1] = 1;
argv[2] = (int)fp;
__try_again:
int ret = os_taskq_post_type(GPU_TASK_NAME, Q_CALLBACK, 3, argv);
if (ret) {
if (retry) {
os_time_dly(1);
retry--;
goto __try_again;
}
printf("%s post ret:%d retry:%d\n", __func__, ret, retry);
}
return ret;
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_release_async 异步释放接口,post到gpu_task执行
*
* @param opj
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_opj_release_async(void *opj)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
log_debug("%s 0x%x opj:%x", __func__, rets, opj);
if (opj) {
/*同步到gpu线程释放,避免gpu在使用jpeg资源*/
jlgpu_scheduler_async_free_jpeg_res(opj);
}
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_init jpeg句柄初始化(初始化硬件、解析文件头)
*
* @param priv
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_opj_init(void *priv)
{
jdec_opj *opj = (jdec_opj *)priv;
void *dev = opj->device;
int ret = jljpeg_decode_init(opj);
if (!ret) {
ret = jljpeg_img_info_get(opj, jlui_jpeg_infunc_bits_stream, dev);
#if 0
wdt_clear();
FILE *fp = fopen("storage/sd0/C/debug/test****.jpg", "w+");
if (fp) {
struct flash_file_info *image_info = (struct flash_file_info *)opj->device;
printf("buf:0x%x len:%d", image_info->offset, image_info->last_tab_data_len);
fwrite((u8 *)image_info->offset, 1, image_info->last_tab_data_len, fp);
fclose(fp);
os_time_dly(1);
}
ASSERT(!ret, "jpeg file notsupport err:%x", ret);
#endif
if (ret) {
log_warn("%s err:%d", __func__, ret);
}
}
log_debug("%s %d", __func__, ret);
return ret;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_create 创建jpeg句柄
*
* @param dev
* @param dev_len
* @param check
* @param index
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
void *jpeg_module_opj_create(void *dev, int dev_len, u32 check, u32 index, u32 task_id, u32 elm_id)
{
int ret;
struct jpeg_hd_manager *hd = jpeg_hd_manager_check(check);
jdec_opj *opj = NULL;
if (!hd) {
opj = jpeg_malloc(sizeof(jdec_opj));
hd = jpeg_hd_manager_add(opj, check);
opj->device = jpeg_malloc(dev_len);
memcpy(opj->device, dev, dev_len);
ret = jpeg_module_opj_init((void *)opj);
if (ret) {
log_debug("%s %d", __func__, __LINE__);
jpeg_module_opj_release_async((void *)opj);
opj = NULL;
}
hd->task_id = task_id;
hd->elm_id = elm_id;
} else {
opj = hd->opj;
}
if (opj) {
jpeg_hd_manager_vaild_set(opj, 1);
}
return (void *)opj;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_set_invaild_by_index 将某个jpeg句柄设为无效
*
* @param index
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_opj_set_invaild_by_index(int index)
{
log_debug("%s %d", __func__, __LINE__);
struct jpeg_hd_manager *p, *n;
ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &__this->entry, entry) {
jpeg_hd_manager_vaild_sub(p->opj);
}
EXIT_CRITICAL();
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_invaild_clr 将无效的句柄清除
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_opj_invaild_clr()
{
log_debug("%s %d", __func__, __LINE__);
struct jpeg_hd_manager *p, *n;
ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &__this->entry, entry) {
if (p->vaild) {
continue;
}
list_del(&(p->entry));
if (p->file_flag) {
FILE *fp = (FILE *)(((int *)p->opj->device)[0]);
jpeg_module_opj_free_file_hd(fp);
}
jpeg_module_opj_release_async(p->opj);
jpeg_free(p);
}
EXIT_CRITICAL();
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_clr_all 清除所有句柄
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_opj_clr_all()
{
log_debug("%s %d", __func__, __LINE__);
return jpeg_hd_manager_clr();
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_init 模块初始化
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_init()
{
INIT_LIST_HEAD(&__this->entry);
return 0;
}
//======================================================================//
// jpeg数据输出输出
//======================================================================//
/* ------------------------------------------------------------------------------------*/
/**
* @brief jlui_jpeg_infunc_bits_stream jpeg数据流
*
* @param opj jpeg句柄
* @param buf jpeg buf
* @param len jpeg读取长度
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
u32 jlui_jpeg_infunc_bits_stream(struct _jdec_opj *opj, u8 *buf, u32 len)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
/* log_debug("%s jpeg_info:%x %x buf:%x rets:0x%x\n", __func__, (int)opj, (int)opj->device, (int)buf, rets); */
//dev句柄,可以是flash_info、ram地址、文件系统句柄等,只需要将
//偏移为opj->curr_offset长度为len数据,copy到buf,并返回实际的copy长度即可
struct flash_file_info *image_info = (struct flash_file_info *)opj->device;
int start_addr, end_addr, curr_addr, read_len;
if (image_info->tab) { //使用mmu_table
int need_len = len;
int poffset = opj->curr_offset;
int curr_offset = 0;
int mmu_idx = (poffset + image_info->offset) / 4096; //计算起始mmu_tab
/* printf("%s offset %d end:%d tbsize:%d", __func__, image_info->offset, image_info->last_tab_data_len, image_info->tab_size / 4); */
do {
//当前mmu块的最大长度
int block_end = (mmu_idx == ((image_info->tab_size / 4) - 1)) ? image_info->last_tab_data_len : 4096;
//当前mmu块的起始偏移
int block_offset = (image_info->offset + poffset) % 4096;
//当前mmu块的可读长度
int block_len = block_end - block_offset;
//拷贝长度
read_len = (block_len < need_len) ? block_len : need_len;
//拷贝地址
curr_addr = image_info->tab[mmu_idx] + block_offset;
/* printf("%s mmu_idx:%d block_end:%d block_offset:%d block_len:%d read_len:%d need_len:%d,poffset:%d curr_offset%d\n", */
/* __func__, mmu_idx, block_end, block_offset, block_len, read_len, need_len, poffset, curr_offset); */
//分块拷贝
if (buf) {
if (norflash_ext_sfc_en && IS_SFC1_ADDR(curr_addr)) {
norflash_espi_mutex_enter();
}
memcpy(buf + curr_offset, (const u8 *)curr_addr, read_len);
if (norflash_ext_sfc_en && IS_SFC1_ADDR(curr_addr)) {
norflash_espi_mutex_exit();
}
}
//计算下一块mmu
poffset += read_len;
curr_offset += read_len;
need_len -= read_len;
if (mmu_idx >= ((image_info->tab_size / 4) - 1)) {//读取完所有mmu
break;
} else {
mmu_idx ++;
}
if (need_len <= 0) {//读取完数据
break;
}
} while (1);
//返回实际读取总长度
read_len = curr_offset;
} else {
//资源起始地址
start_addr = image_info->offset;
//结束地址
end_addr = image_info->offset + image_info->last_tab_data_len;
//拷贝地址
curr_addr = start_addr + opj->curr_offset;
//拷贝长度
read_len = (curr_addr + len > end_addr) ? end_addr - curr_addr : len;
//拷贝
if (buf) {
if (norflash_ext_sfc_en && IS_SFC1_ADDR(curr_addr)) {
norflash_espi_mutex_enter();
}
memcpy(buf, (const u8 *)curr_addr, read_len);
if (norflash_ext_sfc_en && IS_SFC1_ADDR(curr_addr)) {
norflash_espi_mutex_exit();
}
}
}
/* log_debug("%s start_addr:0x%x end_addr:0x%x file_len:%d curr_addr:0x%x len:%d read_len:%d", */
/* __func__, start_addr, end_addr, end_addr - start_addr, curr_addr, len, read_len); */
return read_len;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief 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 jpeg_draw_cb(int id, u8 *dst_buf, struct rect *dst_r, struct rect *src_r, u8 bytes_per_pixel, void *priv, void *matrix)
{
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];//
/* log_debug("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;
}
if (jljpeg_get_decode_hd() && (opj != jljpeg_get_decode_hd())) {
jljpeg_decode_hdl_reset(opj);
/* jljpeg_decode_reset_curr(); */
}
//计算缩放后的区域*以推屏区域、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;
/* log_debug("%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 * dst_r->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 jpeg_draw_cb_gpu gpu绘图回调
*
* @param id
* @param dst_buf
* @param dst_r
* @param src_r
* @param bytes_per_pixel
* @param priv
* @param matrix
*/
/* ------------------------------------------------------------------------------------*/
void jpeg_draw_cb_gpu(int id, u8 *dst_buf, struct rect *dst_r, struct rect *src_r, u8 bytes_per_pixel, void *priv, void *matrix)
{
//先用过id获取句柄,如果获取不到就return
struct jpeg_priv *__jpeg_priv = (struct jpeg_priv *) priv;
struct jpeg_hd_manager *hd = jpeg_hd_manager_find_by_id(__jpeg_priv->task_id, __jpeg_priv->elm_id);
if (!hd) {
log_warn("%s elmid:%d task_id:%d", __func__, __jpeg_priv->elm_id, __jpeg_priv->task_id);
return;
}
jpeg_draw_cb(id, dst_buf, dst_r, src_r, bytes_per_pixel, hd->opj, matrix);
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jlui_draw_jpeg_cb_exit 任务销毁时调用,释放jpeg资源
*
* @param priv jpeg句柄
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_draw_cb_exit(void *draw_info, void *priv)
{
pJLGPUTaskDraw_t __draw_info = (pJLGPUTaskDraw_t)draw_info;
/*使用双任务链推屏时,在息屏前或更新资源句柄前释放jpeg句柄,避免双链表冲突*/
void *opj = __draw_info->priv;
__draw_info->priv = NULL;//由应用层释放
__draw_info->priv_len = 0;
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief cache_gpu_input_jpeg_data_cb 将数据拷贝到psram
*
* @param priv jpeg句柄
* @param dst 解码后的输出buf
* @param src NULL
* @param len 0
*/
/* ------------------------------------------------------------------------------------*/
void cache_gpu_input_jpeg_data_cb(void *priv, void *dst, void *src, int len)
{
jdec_opj *jpg_hd = (jdec_opj *)priv;
//解码
struct rect jpeg_dec = {
.left = 0,
.top = 0,
.width = jpg_hd->width,
.height = jpg_hd->height,
};
int bytes_per_pixel = 2;
u32 jpeg_width_align = (jpeg_dec.width + 15) / 16 * 16;
u32 jpeg_height_align = (jpg_hd->height + 15) / 16 * 16;
u32 jpeg_stride = bytes_per_pixel * jpeg_width_align ;
u8 *tmp_buf = malloc_psram(jpeg_stride * jpeg_height_align);
jlgpu_scheduler_wait_sync();
extern int ui_disp_out_stride_set(u16 stride);
ui_disp_out_stride_set(jpeg_stride);
struct rect dst_r = {
.left = 0,
.top = 0,
.width = jpeg_width_align,
.height = jpeg_height_align,
};
jpeg_draw_cb(0, tmp_buf, &dst_r, &jpeg_dec, bytes_per_pixel, jpg_hd, NULL);
UI_IO_DEBUG_1(B, 6)
texture_line_to_tile_base(dst, tmp_buf, jpeg_width_align, jpeg_height_align, GPU_FORMAT_RGB565);
UI_IO_DEBUG_0(B, 6)
free_psram(tmp_buf);
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief cache_gpu_input_jpeg_data 解码jpeg图片到psram
*
* @param head 预留
* @param task_param gpu任务参数
* @param fp jpeg文件指针
* @param index 任务链索引,一般为0、1
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
void *cache_gpu_input_jpeg_data(void *head, pJLGPUTaskParam_t task_param, void *fp, int index)
{
/* 检查是否已经有缓存,如果需要缓存jpg没在cache里,释放原来的,缓存新的 */
void *cache_addr = gpu_input_stream_cache_check(task_param->image.data_crc);
//jpeg原始数据,nand使用
u8 *jpeg_src_data = NULL;
int vaild_index = index;
/* printf("@@@@@ cache_addr: 0x%x\n crc:%d", (u32)cache_addr,task_param->image.data_crc); */
if (!cache_addr) {//解码jpeg到psram
jdec_opj *jpg_hd = jpeg_malloc(sizeof(jdec_opj)); //在任务销毁时释放
jpg_hd->device = jpeg_malloc(sizeof(struct flash_file_info));//设备句柄,这里可以是文件句柄等,搭配input_steam使用
#if TCFG_NANDFLASH_DEV_ENABLE
if (fp) {
//文件头解析的时候比较零散,这里直接将文件拷贝到psram,解完后free
UI_IO_DEBUG_1(B, 2);
jpeg_src_data = jpeg_malloc(task_param->image.len);
res_fseek(fp, (u32)task_param->image.offset, SEEK_SET);
res_fread(fp, jpeg_src_data, task_param->image.len);
struct flash_file_info *p_info = (struct flash_file_info *)jpg_hd->device;
p_info->offset = (u32)jpeg_src_data;
p_info->tab = NULL;
p_info->tab_size = 0;
p_info->last_tab_data_len = task_param->image.len;
UI_IO_DEBUG_0(B, 2);
} else {
ASSERT(0);
}
#else
memcpy(jpg_hd->device, &task_param->info, sizeof(struct flash_file_info));
#endif
UI_IO_DEBUG_1(B, 4);
if (jpeg_module_opj_init(jpg_hd)) {//初始化jpeg头
//异常释放资源
jpeg_free(jpg_hd->device);
jljpeg_decode_release(jpg_hd, 0);
jpeg_free(jpg_hd);
if (jpeg_src_data) {
jpeg_free(jpeg_src_data);
}
return NULL;
}
//cache
/* u32 jpeg_stride = 2 * (jpg_hd->width + 7) / 8 * 8; */
/* u32 jpeg_height_align = (jpg_hd->height + 7) / 8 * 8; */
u32 jpeg_width_align = (jpg_hd->width + 15) / 16 * 16;
u32 jpeg_stride = 2 * jpeg_width_align;
u32 jpeg_height_align = (jpg_hd->height + 15) / 16 * 16;
u32 jpeg_img_len = jpeg_stride * jpeg_height_align ;
cache_addr = gpu_input_stream_cache_add_with_callback(jpg_hd, jpg_hd, jpeg_img_len,
task_param->image.data_crc, NULL, 0, cache_gpu_input_jpeg_data_cb);
//从cache同步到物理介质,后续用nocache直接访问
psram_flush_cache(cache_addr, jpeg_img_len);
jpeg_free(jpg_hd->device);
jljpeg_decode_release(jpg_hd, 1);
jpeg_free(jpg_hd);
if (jpeg_src_data) {
jpeg_free(jpeg_src_data);
}
UI_IO_DEBUG_0(B, 4);
}
//使用nocache地址访问,提高读效率
task_param->texture.data = psram_cache_2_nocache(cache_addr);
/* task_param->texture.data =(cache_addr); */
//更新任务配置
task_param->texture.mmu_tab_base = NULL;
task_param->format = GPU_FORMAT_RGB565;
task_param->texture.not_compress = 1;
task_param->texture.adr_mode = 0;
int width = task_param->image.width;
int height = task_param->image.height;
task_param->image.width = (width + 15) / 16 * 16;
task_param->image.height = (height + 15) / 16 * 16;
if (cache_addr) {
gpu_input_stream_cache_vaild_value_set_by_index((u32)cache_addr, 3);
gpu_input_stream_cache_set_index((u32)cache_addr, index);
}
return task_param->texture.data;
}
/* ------------------------------------------------------------------------------------*/
/**
* @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));
if (buf) {
FILE *fp = (FILE *)(((int *)opj->device)[0]);
/* printf("%s fp:0x%x",__func__,(u32)fp); */
/* printf("%s offset:%d len:%d end:%d\n", __func__, opj->curr_offset,len,flen(fp)); */
fseek(fp, opj->curr_offset, SEEK_SET);
return fread(buf, len, 1, fp);
} else {
return len;
}
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_init jpeg句柄初始化(初始化硬件、解析文件头)
*
* @param priv
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_module_opj_init_file(void *priv)
{
jdec_opj *opj = (jdec_opj *)priv;
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);
}
log_debug("%s %d", __func__, ret);
return ret;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_module_opj_create 创建jpeg句柄
*
* @param dev
* @param dev_len
* @param check
* @param index
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
void *jpeg_module_opj_create_file(void *path, int path_len, u32 check, u32 index, u32 task_id, u32 elm_id)
{
int ret;
struct jpeg_hd_manager *hd = jpeg_hd_manager_check(check);
jdec_opj *opj = NULL;
if (!hd) {
opj = jpeg_malloc(sizeof(jdec_opj));
hd = jpeg_hd_manager_add(opj, check);
void *dev = (void *)fopen(path, "r");
printf("%s [FILE] fp:0x%x ", __func__, (u32)dev);
int dev_len = sizeof(FILE *);
hd->file_flag = 1;
opj->device = jpeg_malloc(dev_len);
memcpy(opj->device, &dev, dev_len);
ret = jpeg_module_opj_init_file((void *)opj);
if (ret) {
log_debug("%s %d", __func__, __LINE__);
jpeg_module_opj_release_async((void *)opj);
opj = NULL;
}
hd->task_id = task_id;
hd->elm_id = elm_id;
} else {
opj = hd->opj;
}
if (opj) {
jpeg_hd_manager_vaild_set(opj, 1);
}
return (void *)opj;
}
@@ -0,0 +1,616 @@
/* #include "app_task.h" */
#include "system/timer.h"
#include "device/device.h"
#include "key_event_deal.h"
#include "res/resfile.h"
#include "jlui/ui.h"
#include "jlui_app/ui_style.h"
#include "jlui_app/ui_api.h"
#include "jlui_app/res_config.h"
#include "jlui_app/ui_resource.h"
#include "jlui_app/ui_sys_param.h"
#include "ui_draw/ui_type.h"
#include "jlgpu_math.h" // matrix
#include "jlgpu_driver.h" // gpu 驱动
#include "gpu_port.h" // GPU 接口,依赖于 jlgpu_driver.h
#include "gpu_task.h"
#include "jljpeg_decode.h"
#include "jpeg_stream.h"
#include "video/avi/avilib.h"
#define LOG_TAG_CONST JPEG
#define LOG_TAG "[JPEG_STREAM]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define JPEG_STREAM_ALLOC malloc_psram
#define JPEG_STREAM_FREE free_psram
#define JPEG_STREAM_SPIN_LOCK_EN 1
struct jpeg_stream_info {
// jpeg原图
u8 *src_buf;
int src_len;
volatile u8 data_lock;
u16 idx;
#if JPEG_STREAM_SPIN_LOCK_EN
spinlock_t lock;
#else
OS_MUTEX lock;
#endif
} __jpeg_stream_info;
#define __this (&__jpeg_stream_info)
#if JPEG_STREAM_SPIN_LOCK_EN
#define JPEG_STREAM_LOCK_INIT spin_lock_init(&__this->lock);
#define JPEG_STREAM_LOCK spin_lock(&__this->lock);
#define JPEG_STREAM_UNLOCK spin_unlock(&__this->lock);
#else
#define JPEG_STREAM_LOCK_INIT os_mutex_create(&__this->lock);
#define JPEG_STREAM_LOCK os_mutex_pend(&__this->lock);
#define JPEG_STREAM_UNLOCK os_mutex_post(&__this->lock);
#endif
#define GPU_TASK_ID(page, id, index) ((page << 26) | (0 << 24) | (id << 8) | index)
extern u32 usr_mmu_hash(u32 hash, u8 *data, int len);
extern void *jpeg_module_opj_create_file(void *path, int path_len, u32 check, u32 index, u32 task_id, u32 elm_id);
extern void *jpeg_module_opj_create(void *dev, int dev_len, u32 check, u32 index, u32 task_id, u32 elm_id);
extern int jpeg_module_opj_clr_all();
extern void *jpeg_hd_create_priv(u32 task_id, u32 elm_id);
extern int jpeg_hd_get_priv_len();
extern void jpeg_draw_cb_gpu(int id, u8 *dst_buf, struct rect *dst_r, struct rect *src_r, u8 bytes_per_pixel, void *priv, void *matrix);
extern void jlui_free(void *buf, u32 ram_type, u32 module_type);
extern int jpeg_module_opj_init(void *priv);
extern int jljpeg_decode_release(jdec_opj *opj, int global_hd_clr);
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_init jpeg数据流初始化
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jljpeg_stream_init()
{
JPEG_STREAM_LOCK_INIT;
__this->data_lock = 0;
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_deinit
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jljpeg_stream_deinit()
{
JPEG_STREAM_LOCK;
__this->data_lock = 1;
__this->src_len = 0;
JPEG_STREAM_FREE(__this->src_buf);
__this->src_buf = NULL;
JPEG_STREAM_UNLOCK;
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_lock 数据锁保护
*/
/* ------------------------------------------------------------------------------------*/
void jljpeg_stream_src_data_lock()
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
log_debug("<%s> rets:%x\n", __func__, rets);
JPEG_STREAM_LOCK;
__this->data_lock = 1;
JPEG_STREAM_UNLOCK;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_unlock 数据解锁保护
*/
/* ------------------------------------------------------------------------------------*/
void jljpeg_stream_src_data_unlock()
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
log_debug("<%s> rets:%x\n", __func__, rets);
JPEG_STREAM_LOCK;
__this->data_lock = 0;
JPEG_STREAM_UNLOCK;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_lock_check 查询锁状态
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jljpeg_stream_src_data_lock_check()
{
return __this->data_lock;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_copy 输入数据并拷贝到psram缓存
*
* @param buf
* @param size
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jljpeg_stream_src_data_copy(u8 *buf, int size)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
log_debug("<%s> rets:%x size:%d\n", __func__, rets, size);
if (jljpeg_stream_src_data_lock_check()) {
return -1;
}
JPEG_STREAM_LOCK;
if (__this->src_buf) {
JPEG_STREAM_FREE(__this->src_buf);
}
log_debug("%s line:%d buf:%x", __func__, __LINE__, (u32)__this->src_buf);
__this->src_len = size;
__this->src_buf = JPEG_STREAM_ALLOC(size);
memcpy(__this->src_buf, buf, size);
__this->idx++;
log_debug("%s line:%d buf:%x", __func__, __LINE__, (u32)__this->src_buf);
JPEG_STREAM_UNLOCK;
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_len_get 获取缓存数据长度
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jljpeg_stream_src_data_len_get()
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
log_debug("<%s> rets:%x len:%d\n", __func__, rets, __this->src_len);
return __this->src_len;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_get 获取缓存数据地址
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
u8 *jljpeg_stream_src_data_get()
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
log_debug("<%s> rets:%x buf:0x%x\n", __func__, rets, (u32)__this->src_buf);
return __this->src_buf;
}
void camera_manager_resume(void);
void camera_manager_suspend(void);
/* ------------------------------------------------------------------------------------*/
/**
* @brief jljpeg_stream_src_data_save_to_file 将缓存数据写入到文件
*
* @param filename 路径
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jljpeg_stream_src_data_save_to_file(s8 *filename)
{
int has_photo = 0;
//100ms 足够编完一帧
for (int i = 0; i < 10; i++) {
if (jljpeg_stream_src_data_len_get()) {
log_debug("%s %d", __func__, __LINE__);
has_photo = 1;
break;
}
os_time_dly(1);
}
if (!has_photo) {
return -1;
}
/* camera_manager_suspend(); */
/* wdt_clear(); */
FILE *fp = fopen(filename, "w+");
log_debug("%s file_name:%s save ", __func__, filename);
if (fp) {
fwrite(jljpeg_stream_src_data_get(), 1, jljpeg_stream_src_data_len_get(), fp);
u8 name[17] = {0};
fget_name(fp, name, 16);
log_info("%s file_name:%s real_name:%s save succ!!!", __func__, filename, name);
fclose(fp);
}
/* camera_manager_resume(); */
return 0;
}
static void jpeg_task_cb_exit(void *draw_info, void *priv)
{
/* jpeg_data_lock_unlock(); */
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_image_ram 从ram中加载jpeg显示
*
* @param dc
* @param left
* @param top
* @param width
* @param height
* @param addr jpeg地址
* @param len
*/
/* ------------------------------------------------------------------------------------*/
void jpeg_image_ram(struct draw_context *dc, int left, int top, int width, int height, u8 *addr, int len)
{
jljpeg_stream_src_data_lock();
int elm_id = dc->elm->id;
u8 elm_index = 1;
u16 idx = __this->idx;
elm_index = dc->elm_index++;
int task_id = GPU_TASK_ID(dc->page, idx, elm_index);
jlgpu_task_basic_param_init(GPU_TASK_IMAGE, task_id, elm_id);
task_param.priority = dc->elm->prior;
task_param.image.width = width;
task_param.image.height = height;
struct rect image_rect;
image_rect.left = left;
image_rect.top = top;
image_rect.width = task_param.image.width;
image_rect.height = task_param.image.height;
// if (!get_rect_align(&dc->rect, &image_rect, dc->hori_align, dc->vert_align)) {
// return ;
// }
jlgpu_get_win_rect(&task_param.area);
task_param.info.offset = (u32)addr;
task_param.info.last_tab_data_len = len;
/* printf("%s %d %d", __func__, task_param.info.offset, task_param.info.last_tab_data_len); */
get_rect_cover(&dc->rect, &image_rect, &task_param.draw);
/* memcpy(&task_param.draw, &image_rect, sizeof(struct rect)); */
task_param.task_type = GPU_TASK_DRAW;
task_param.cb_func = jpeg_draw_cb_gpu;
/* task_param.cb_exit = jpeg_task_cb_exit; */
u32 res_hash = 5383;
res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.image, sizeof(struct image_file));
res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.task_id, 4);
res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.element_id, 4);
void *opj = jpeg_module_opj_create(&task_param.info, sizeof(struct flash_file_info), res_hash, dc->index, task_param.task_id, task_param.element_id);
if (opj) {
pJLGPUTaskUnit_t taskp = jlgpu_get_task_by_id(dc->gpu_task_head, task_param.task_id, task_param.element_id);
if (taskp && taskp->info.draw_info) {
jlui_free(taskp->info.draw_info->priv, UI_RAM_SRAM, UI_MODULE_FRAME);
}
task_param.priv = jpeg_hd_create_priv(task_param.task_id, task_param.element_id);
task_param.priv_len = jpeg_hd_get_priv_len();
task_param.draw_en = 1;
}
task_param.clut_format = task_param.image.clut_format;
task_param.has_clut = task_param.image.has_clut;
task_param.texture.data = (u8 *)task_param.info.offset;
task_param.texture.mmu_tab_base = (u8 *)task_param.info.tab;
jlgpu_update_task_by_id(dc->gpu_task_head, task_param.task_id, task_param.element_id, &task_param);
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_image_file 从文件加载图片,不缓存
*
* @param dc
* @param left
* @param top
* @param width
* @param height
* @param path 路径
* @param path_len
*/
/* ------------------------------------------------------------------------------------*/
void jpeg_image_file(struct draw_context *dc, int left, int top, int width, int height, u8 *path, int path_len)
{
int elm_id = dc->elm->id;
u8 elm_index = 1;
u16 idx = __this->idx;
elm_index = dc->elm_index++;
int task_id = GPU_TASK_ID(dc->page, idx, elm_index);
jlgpu_task_basic_param_init(GPU_TASK_IMAGE, task_id, elm_id);
task_param.priority = dc->elm->prior;
task_param.image.width = width;
task_param.image.height = height;
struct rect image_rect;
image_rect.left = left;
image_rect.top = top;
image_rect.width = task_param.image.width;
image_rect.height = task_param.image.height;
// if (!get_rect_align(&dc->rect, &image_rect, dc->hori_align, dc->vert_align)) {
// return ;
// }
jlgpu_get_win_rect(&task_param.area);
/* task_param.info.offset = (u32)addr; */
/* task_param.info.last_tab_data_len = len; */
/* printf("%s %d %d", __func__, task_param.info.offset, task_param.info.last_tab_data_len); */
get_rect_cover(&dc->rect, &image_rect, &task_param.draw);
/* memcpy(&task_param.draw, &image_rect, sizeof(struct rect)); */
task_param.task_type = GPU_TASK_DRAW;
task_param.cb_func = jpeg_draw_cb_gpu;
/* task_param.cb_exit = jpeg_task_cb_exit; */
u32 res_hash = 5383;
res_hash = usr_mmu_hash(res_hash, (u8 *)path, path_len);
res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.task_id, 4);
res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.element_id, 4);
void *opj = jpeg_module_opj_create_file((void *)path, path_len, res_hash, dc->index, task_param.task_id, task_param.element_id);
if (opj) {
pJLGPUTaskUnit_t taskp = jlgpu_get_task_by_id(dc->gpu_task_head, task_param.task_id, task_param.element_id);
if (taskp && taskp->info.draw_info) {
jlui_free(taskp->info.draw_info->priv, UI_RAM_SRAM, UI_MODULE_FRAME);
}
task_param.priv = jpeg_hd_create_priv(task_param.task_id, task_param.element_id);
task_param.priv_len = jpeg_hd_get_priv_len();
task_param.draw_en = 1;
}
task_param.clut_format = task_param.image.clut_format;
task_param.has_clut = task_param.image.has_clut;
task_param.texture.data = (u8 *)task_param.info.offset;
task_param.texture.mmu_tab_base = (u8 *)task_param.info.tab;
jlgpu_update_task_by_id(dc->gpu_task_head, task_param.task_id, task_param.element_id, &task_param);
}
extern void cache_gpu_input_jpeg_data_cb(void *priv, void *dst, void *src, int len);
void *cache_gpu_input_jpeg_data_file(void *head, pJLGPUTaskParam_t task_param, u32 check, char *path)
{
/* 检查是否已经有缓存,如果需要缓存jpg没在cache里,释放原来的,缓存新的 */
void *cache_addr = gpu_input_stream_cache_check(check);
//jpeg原始数据,nand使用
u8 *jpeg_src_data = NULL;
int jpeg_src_data_len = 0;
log_debug("@@@@@ cache_addr: 0x%x\n crc:0x%x path:%s", (u32)cache_addr, check, path);
if (!cache_addr) {//解码jpeg到psram
log_debug("%s path%s", __func__, path);
if (strstr(path, "avi") || strstr(path, "AVI")) {
log_debug("AVI");
wdt_clear();
#if 0//限制文件大小
FILE *avi_fp = fopen(path, "r");
int avi_len = flen(avi_fp);
fclose(avi_fp);
if (avi_len > 80 * 1024 * 1024) {
return NULL;
}
#endif
#if 1//只解第一帧数据,内存开销小。code by ds
int get_first_video_frame_info(const char *filename, int *offset, int *size);
int frame_pos = 0, frame_len = 0;
get_first_video_frame_info(path, &frame_pos, &frame_len);
log_debug("%s %d pos:%d len:%d", __func__, __LINE__, frame_pos, frame_len);
if (frame_len <= 0) {
return NULL;
}
jpeg_src_data_len = frame_len;
if (jpeg_src_data_len <= 0) {
log_warn("%s %d", __func__, __LINE__);
return NULL;
}
jpeg_src_data = jpeg_malloc(jpeg_src_data_len);
FILE *fp = fopen(path, "r");
if (fp) {
fseek(fp, frame_pos, SEEK_SET);
fread(jpeg_src_data, jpeg_src_data_len, 1, fp);
fclose(fp);
fp = NULL;
}
#else//按avilib流程打开文件,内存开销都大
avi_t *in_fd = AVI_open_input_file(path, 1);
if (in_fd) {
int frame_idx = 0;
#if 1//先拿到pos和len,再申请内存
int AVI_get_video_frame_info(avi_t * AVI, int frame, int *pos, int *len);
int pos, len = 0;
AVI_get_video_frame_info(in_fd, frame_idx, &pos, &len);
AVI_close(in_fd);
log_debug("%s %d pos:%d len:%d", __func__, __LINE__, pos, len);
jpeg_src_data_len = len;
if (jpeg_src_data_len <= 0) {
log_warn("%s %d", __func__, __LINE__);
return NULL;
}
jpeg_src_data = jpeg_malloc(jpeg_src_data_len);
FILE *fp = fopen(path, "r");
if (fp) {
fseek(fp, pos, SEEK_SET);
fread(jpeg_src_data, jpeg_src_data_len, 1, fp);
fclose(fp);
fp = NULL;
}
#else//先申请内存,再释放文件
jpeg_src_data_len = AVI_frame_size(in_fd, frame_idx);
if (jpeg_src_data_len <= 0) {
/* AVI_close(in_fd); */
log_warn("%s %d", __func__, __LINE__);
return NULL;
}
jpeg_src_data = jpeg_malloc(jpeg_src_data_len);
AVI_set_video_position(in_fd, frame_idx);
int key_frame;
AVI_read_frame(in_fd, (char *)jpeg_src_data, &key_frame);
AVI_close(in_fd);
#endif
} else {
return NULL;
}
#endif
} else {
log_debug("JPEG");
FILE *fp = fopen(path, "r");
if (fp) {
//文件头解析的时候比较零散,这里直接将文件拷贝到psram,解完后free
jpeg_src_data_len = flen(fp);
jpeg_src_data = jpeg_malloc(jpeg_src_data_len);
fseek(fp, 0, SEEK_SET);
fread(jpeg_src_data, jpeg_src_data_len, 1, fp);
fclose(fp);
}
}
log_debug("%s dat:%x len%d\n", __func__, (u32)jpeg_src_data, jpeg_src_data_len);
if (jpeg_src_data == NULL) {
log_error("path:%s not find\n", path);
return 0;
}
jdec_opj *jpg_hd = jpeg_malloc(sizeof(jdec_opj)); //在任务销毁时释放
jpg_hd->device = jpeg_malloc(sizeof(struct flash_file_info));//设备句柄,这里可以是文件句柄等,搭配input_steam使用
struct flash_file_info *p_info = (struct flash_file_info *)jpg_hd->device;
p_info->offset = (u32)jpeg_src_data;
p_info->tab = NULL;
p_info->tab_size = 0;
p_info->last_tab_data_len = jpeg_src_data_len;
if (jpeg_module_opj_init(jpg_hd)) {//初始化jpeg头
//异常释放资源
jpeg_free(jpg_hd->device);
jljpeg_decode_release(jpg_hd, 0);
jpeg_free(jpg_hd);
if (jpeg_src_data) {
jpeg_free(jpeg_src_data);
}
return NULL;
}
//cache
/* u32 jpeg_stride = 2 * (jpg_hd->width + 7) / 8 * 8; */
/* u32 jpeg_height_align = (jpg_hd->height + 7) / 8 * 8; */
u32 jpeg_width_align = (jpg_hd->width + 15) / 16 * 16;
u32 jpeg_stride = 2 * jpeg_width_align;
u32 jpeg_height_align = (jpg_hd->height + 15) / 16 * 16;
u32 jpeg_img_len = jpeg_stride * jpeg_height_align ;
cache_addr = gpu_input_stream_cache_add_with_callback(jpg_hd, jpg_hd, jpeg_img_len,
check, NULL, 0, cache_gpu_input_jpeg_data_cb);
//从cache同步到物理介质,后续用nocache直接访问
/* psram_flush_cache(cache_addr, jpeg_img_len); */
jpeg_free(jpg_hd->device);
jljpeg_decode_release(jpg_hd, 1);
jpeg_free(jpg_hd);
if (jpeg_src_data) {
jpeg_free(jpeg_src_data);
}
}
//使用nocache地址访问,提高读效率
/* task_param->texture.data = psram_cache_2_nocache(cache_addr); */
task_param->texture.data = (cache_addr);
//更新任务配置
task_param->texture.mmu_tab_base = NULL;
task_param->format = GPU_FORMAT_RGB565;
task_param->texture.not_compress = 1;
task_param->texture.adr_mode = 0;
int width = task_param->image.width;
int height = task_param->image.height;
task_param->image.width = (width + 15) / 16 * 16;
task_param->image.height = (height + 15) / 16 * 16;
if (cache_addr) {
gpu_input_stream_cache_vaild_value_set_by_index((u32)cache_addr, 3);
}
return task_param->texture.data;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jpeg_image_file_psram 从文件加载jpeg解码到psram
*
* @param dc
* @param left
* @param top
* @param width
* @param height
* @param path 路径
* @param path_len
* @param scale_en 缩放
* @param scale_f
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int jpeg_image_file_psram(struct draw_context *dc, int left, int top, int width, int height, char *path, int path_len, int scale_en, float scale_f)
{
int elm_id = dc->elm->id;
u8 elm_index = 1;
u16 idx = __this->idx;
elm_index = dc->elm_index++;
int task_id = GPU_TASK_ID(dc->page, idx, elm_index);
jlgpu_task_basic_param_init(GPU_TASK_IMAGE, task_id, elm_id);
task_param.priority = dc->elm->prior;
task_param.image.width = width;
task_param.image.height = height;
struct rect image_rect;
image_rect.left = left;
image_rect.top = top;
image_rect.width = task_param.image.width;
image_rect.height = task_param.image.height;
jlgpu_get_win_rect(&task_param.area);
get_rect_cover(&dc->rect, &image_rect, &task_param.draw);
task_param.task_type = GPU_TASK_IMAGE;
u32 res_hash = 5383;
res_hash = usr_mmu_hash(res_hash, (u8 *)path, path_len);
/* res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.task_id, 4); */
/* res_hash = usr_mmu_hash(res_hash, (u8 *)&task_param.element_id, 4); */
task_param.clut_format = task_param.image.clut_format;
task_param.has_clut = task_param.image.has_clut;
task_param.texture.data = (u8 *)task_param.info.offset;
task_param.texture.mmu_tab_base = (u8 *)task_param.info.tab;
task_param.texture.data = cache_gpu_input_jpeg_data_file(dc->gpu_task_head, &task_param, res_hash, path);
if (!task_param.texture.data) {
log_warn("%s %d", __func__, __LINE__);
return -1;
}
//加个缩放
task_param.scale_en = scale_en;
task_param.texture.tran.ratio_w = scale_f;
task_param.texture.tran.ratio_h = scale_f;
if (task_param.texture.data) {
jlgpu_update_task_by_id(dc->gpu_task_head, task_param.task_id, task_param.element_id, &task_param);
}
return 0;
}
@@ -0,0 +1,21 @@
#ifndef __jpeg_stream__
#define __jpeg_stream__
#include "app_config.h"
int jljpeg_stream_init();
int jljpeg_stream_deinit();
void jljpeg_stream_src_data_lock();
void jljpeg_stream_src_data_unlock();
int jljpeg_stream_src_data_lock_check();
int jljpeg_stream_src_data_copy(u8 *buf, int size);
int jljpeg_stream_src_data_len_get();
u8 *jljpeg_stream_src_data_get();
int jljpeg_stream_src_data_save_to_file(s8 *filename);
void jpeg_image_ram(struct draw_context *dc, int left, int top, int width, int height, u8 *addr, int len);
void jpeg_image_file(struct draw_context *dc, int left, int top, int width, int height, u8 *path, int path_len);
int jpeg_image_file_psram(struct draw_context *dc, int left, int top, int width, int height, char *path, int path_len, int scale_en, float scale_f);
#endif// __jpeg_stream__
@@ -0,0 +1,61 @@
#include "app_config.h"
#include "includes.h"
#include "dbi.h"
#include "lcd_task.h"
struct lcd_task_private_def {
u8 has_init;
};
static struct lcd_task_private_def lcd_task_priv ALIGNED(4) = {0};
#define __this (&lcd_task_priv)
void jllcd_task(void *p)
{
int ret;
int msg[32] = {0};
while (1) {
ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
if (ret != OS_TASKQ) {
continue;
}
/* put_buf((u8 *)msg, 32); */
/* printf("%s(), msg: %d, flush: %d, area[%d, %d, %d, %d], addr: 0x%x, hdl: 0x%x\n", \ */
/* __func__, msg[0], msg[1], msg[2], msg[3], msg[4], msg[5], msg[6], msg[7]); */
switch (msg[0]) {
case LCD_MSG_FLUSH:
// 消息格式:刷屏动作,刷屏标志,刷屏区域,刷屏buf,buf句柄
switch (msg[1]) {
case LCD_FLUSH_SET_AREA:
lcd_set_draw_area(msg[2], msg[3], msg[4], msg[5]);
break;
case LCD_FLUSH_KISTART:
extern void lcd_wait_te_sync();
lcd_wait_te_sync(); // 等待TE同步
lcd_set_draw_area(msg[2], msg[3], msg[4], msg[5]); // 设置绘制区域
lcd_draw_kistart((u8 *)msg[6], msg[2], msg[3], msg[4], msg[5]); // 开始绘制
break;
case LCD_FLUSH_CONTINUE:
lcd_draw_continue((u8 *)msg[6], msg[2], msg[3], msg[4], msg[5]);
break;
default:
break;
}
break;
case LCD_MSG_OTHER:
break;
default:
break;
}
}
}
@@ -0,0 +1,29 @@
#ifndef __PUBLIC_LCD_TASK_H__
#define __PUBLIC_LCD_TASK_H__
// LCD 任务名称
#define LCD_TASK_NAME "lcd"
// LCD 消息类型
typedef enum {
LCD_MSG_OTHER, // 默认消息
LCD_MSG_FLUSH, // 刷屏消息
} lcd_task_msg_t;
// 刷屏动作标志
typedef enum {
LCD_FLUSH_SET_AREA, // 设置刷屏区域
LCD_FLUSH_KISTART, // 启动刷屏
LCD_FLUSH_CONTINUE, // 续传
} lcd_flush_flag_t;
void jllcd_task(void *p);
#endif
@@ -0,0 +1,668 @@
#include "system/includes.h"
#include "app_config.h"
#include "ui_core.h"
#include "control.h"
//UI框架RAM统计使能
/* #define UI_BUF_DEBUG //内存debug */
/* #define UI_BUF_CALC_LITE //轻量级统计 */
/* #define UI_BUF_CALC //分模块统计 */
#define LOG_TAG_CONST UI_BUF
#define LOG_TAG "[ui_buf]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_UI_ENABLE
extern size_t xPortGetPhysiceMemorySize(void);
extern const u32 config_ui_alloc_psram_mod_sel;
/***************************************************************/
// UI_BUF_CALC
/***************************************************************/
#ifdef UI_BUF_CALC
struct buffer_calc {
struct list_head list;
u8 *buf;
int size;
u32 ram_type;
u32 module_type;
};
static struct buffer_calc buffer_used = {
.list = {
.next = &buffer_used.list,
.prev = &buffer_used.list,
},
};
static int jlui_malloc_cnt = 0;
/* RAM 类型名 */
const static char *ui_ram_type_name[] = {
"sram",
"param",
"cache",
};
/* 统计各模块内存占用数量 */
struct ui_module_name_def {
char name[24]; // 模块名称
int module; // 模块ID
int sram; // 模块申请sram数量
int other_ram; // psram or cache
int count; // 模块申请内存次数
};
#define WIDGET(type) ((type << 16) | UI_MODULE_WIDGET)
static struct ui_module_name_def ui_module_name[] = {
{"ui_core", UI_MODULE_CORE, 0, 0, 0},
{"ui_frame", UI_MODULE_FRAME, 0, 0, 0},
{"ui_resource", UI_MODULE_RESOURCE, 0, 0, 0},
{"ui_gpu", UI_MODULE_GPU, 0, 0, 0},
{"ui_dbi", UI_MODULE_DBI, 0, 0, 0},
{"ui_font", UI_MODULE_FONT, 0, 0, 0},
{"buf_manager", UI_MODULE_BUFFER, 0, 0, 0},
{"gpu_cache", UI_MODULE_CACHE, 0, 0, 0},
{"jpeg ", UI_MODULE_JPEG, 0, 0, 0},
{"window", WIDGET(CTRL_TYPE_WINDOW), 0, 0, 0},
{"layout", WIDGET(CTRL_TYPE_LAYOUT), 0, 0, 0},
{"layer", WIDGET(CTRL_TYPE_LAYER), 0, 0, 0},
{"grid ", WIDGET(CTRL_TYPE_GRID), 0, 0, 0},
{"list ", WIDGET(CTRL_TYPE_LIST), 0, 0, 0},
{"button", WIDGET(CTRL_TYPE_BUTTON), 0, 0, 0},
{"pic ", WIDGET(CTRL_TYPE_PIC), 0, 0, 0},
{"battery", WIDGET(CTRL_TYPE_BATTERY), 0, 0, 0},
{"time ", WIDGET(CTRL_TYPE_TIME), 0, 0, 0},
{"camera", WIDGET(CTRL_TYPE_CAMERA_VIEW), 0, 0, 0},
{"text ", WIDGET(CTRL_TYPE_TEXT), 0, 0, 0},
{"animation", WIDGET(CTRL_TYPE_ANIMATION), 0, 0, 0},
{"player", WIDGET(CTRL_TYPE_PLAYER), 0, 0, 0},
{"number", WIDGET(CTRL_TYPE_NUMBER), 0, 0, 0},
{"progress", WIDGET(CTRL_TYPE_PROGRESS), 0, 0, 0},
{"multiprogress", WIDGET(CTRL_TYPE_MULTIPROGRESS), 0, 0, 0},
{"watch", WIDGET(CTRL_TYPE_WATCH), 0, 0, 0},
{"slider", WIDGET(CTRL_TYPE_SLIDER), 0, 0, 0},
{"vslider", WIDGET(CTRL_TYPE_VSLIDER), 0, 0, 0},
{"compass", WIDGET(CTRL_TYPE_COMPASS), 0, 0, 0},
};
static void ui_module_ram_change(int ram_type, int module_type, int size, int add) // add 表示size符号,+1/-1
{
int i;
int operator = ((add > 0) ? (1) : (-1));
for (i = 0; i < ARRAY_SIZE(ui_module_name); i++) {
if (ui_module_name[i].module == module_type) {
if (ram_type == UI_RAM_SRAM) {
ui_module_name[i].sram += (operator * size);
} else {
ui_module_name[i].other_ram += (operator * size);
}
ui_module_name[i].count += (operator);
printf("[BUF_CALC]=====>>> %s %s sram %d,other_ram:%d total: %d, count: %d\n",
ui_module_name[i].name, ((operator > 0) ? "malloc" : "free"), size, ui_module_name[i].sram, ui_module_name[i].other_ram, ui_module_name[i].count);
return;
}
}
printf("[BUF_CALC]=====>>> unknow module type: %d, size: %d, add: %d\n", module_type, size, add);
}
void ui_module_ram_dump()
{
int i;
for (i = 0; i < ARRAY_SIZE(ui_module_name); i++) {
printf("[BUF_CALC]=====>>> module: %s \t sram_size: %d \t other_ram:%d \t count: %d\n",
ui_module_name[i].name, ui_module_name[i].sram, ui_module_name[i].other_ram, ui_module_name[i].count);
}
}
void ui_buf_calc_add(void *buf, int size, u32 ram_type, u32 module_type)
{
jlui_malloc_cnt += 1;
struct buffer_calc *new = (struct buffer_calc *)malloc(sizeof(struct buffer_calc));
new->buf = buf;
new->size = size;
new->ram_type = ram_type;
new->module_type = module_type;
list_add_tail((struct list_head *)new, (struct list_head *)&buffer_used);
/* 打印申请的buf地址,buf大小,buf类型,申请模块 */
printf("platform_malloc : 0x%x, size: %d, ram: %s\n", (int)buf, size, ui_ram_type_name[ram_type]);
int real_type = -1;
if (memory_in_vtl(buf)) {
real_type = UI_RAM_SRAM;
}
/* 如果是UI控件申请,打印该UI控件申请的buf总大小 */
ui_module_ram_change(real_type, module_type, size, 1);
/* ui_module_ram_dump(); */
/* 统计整个UI框架申请的buf大小 */
struct buffer_calc *p;
int buffer_used_total = 0;
list_for_each_entry(p, &buffer_used.list, list) {
buffer_used_total += p->size;
}
printf("%s() =====>>> used buffer size:%d, malloc count: %d\n\n", __func__, buffer_used_total, jlui_malloc_cnt);
}
void ui_buf_calc_sub(void *buf, u32 ram_type, u32 module_type)
{
jlui_malloc_cnt -= 1;
struct buffer_calc *p, *n;
int size = 0;
list_for_each_entry_safe(p, n, &buffer_used.list, list) {
if (p->buf == buf) {
/* 如果释放的ram类型和记录的不一样,打印警报 */
if (p->ram_type != ram_type) {
printf("[Warning]: platform_free ram type, excepted: %s, actual: %s\n",
ui_ram_type_name[p->ram_type], ui_ram_type_name[ram_type]);
}
/* 如果释放的模块和记录的不一样,打印警报 */
if (p->module_type != module_type) {
printf("[Warning]: platform_free module type, excepted: %d, actual: %d\n", p->module_type, module_type);
module_type = p->module_type;//使用记录的module
}
size = p->size;
/* 打印释放的buf地址,buf大小,buf类型,释放模块 */
printf("platform_free : 0x%x, size: %d, ram: %s, module: %d\n",
(int)p->buf, p->size, ui_ram_type_name[ram_type], module_type);
__list_del_entry((struct list_head *)p);
free(p);
}
}
int real_type = -1;
if (memory_in_vtl(buf)) {
real_type = UI_RAM_SRAM;
}
/* 如果是UI控件释放,打印该UI控件剩余的buf总大小 */
if (size) {
ui_module_ram_change(real_type, module_type, size, -1);
}
/* ui_module_ram_dump(); */
int buffer_used_total = 0;
list_for_each_entry(p, &buffer_used.list, list) {
buffer_used_total += p->size;
}
printf("%s() =====>>> used buffer size:%d, malloc count: %d\n\n", __func__, buffer_used_total, jlui_malloc_cnt);
}
#endif
/***************************************************************/
// UI_BUF_CALC_LITE
/***************************************************************/
#ifdef UI_BUF_CALC_LITE
static u32 jlui_malloc_total_ram_count = 0; //heap ram size
static u32 jlui_malloc_total_ram_max = 0; //heap ram峰值
static u32 jlui_malloc_total_ram_unuse = 0; //未使用最大数量
static u32 jlui_malloc_total_ram_cnt_max = 0; //ram申请数量统计峰值
static u32 jlui_malloc_total_ram_cnt = 0; //ram申请数量统计
static u32 jlui_malloc_sram_count = 0;
static u32 jlui_malloc_sram_max = 0;
static u32 jlui_malloc_sram_unuse = 0;
static u32 jlui_malloc_sram_cnt_max = 0;
static u32 jlui_malloc_sram_cnt = 0;
#endif
void jlui_malloc_ram_info_dump()
{
#ifdef UI_BUF_CALC_LITE
printf("%s [totalram] curr_size:%d max_size%d curr_block:%d max_block:%d\n", __func__, \
jlui_malloc_total_ram_count, jlui_malloc_total_ram_max, jlui_malloc_total_ram_cnt_max, jlui_malloc_total_ram_cnt);
printf("%s [sram] curr_size:%d max_size%d curr_block:%d max_block:%d unuse_in_max:%d\n", __func__, \
jlui_malloc_sram_count, jlui_malloc_sram_max, jlui_malloc_sram_cnt_max, jlui_malloc_sram_cnt, jlui_malloc_sram_unuse);
#endif
}
void jlui_malloc_ram_info_clr(u8 clr)
{
#ifdef UI_BUF_CALC_LITE
if (clr & BIT(0)) {
jlui_malloc_total_ram_count = 0;
jlui_malloc_sram_count = 0;
}
if (clr & BIT(1)) {
jlui_malloc_total_ram_max = 0;
jlui_malloc_total_ram_cnt_max = 0;
jlui_malloc_sram_max = 0;
jlui_malloc_sram_cnt_max = 0;
}
#endif
}
/***************************************************************/
// CACHE_BUF
/***************************************************************/
#if TCFG_DCACHE_RUN_GPU_BUF || TCFG_ICACHE_RUN_GPU_BUF||TCFG_ICACHE_RUN_FTL_BUF
#include "lbuf.h"
extern u32 dcache_ram_bss_remain_begin;
extern u32 dcache_ram_bss_remain_end;
#define DCACHE_GPU_START (int)(&dcache_ram_bss_remain_begin)
#define DCACHE_GPU_END (int)(&dcache_ram_bss_remain_end)
#define DCACHE_GPU_ADDR (void *)(DCACHE_GPU_START)
#define DCACHE_GPU_SIZE (int)(DCACHE_GPU_END - DCACHE_GPU_START)
extern u32 icache_ram_bss_remain_begin;
extern u32 icache_ram_bss_remain_end;
#define ICACHE_GPU_START (int)(&icache_ram_bss_remain_begin)
#define ICACHE_GPU_END (int)(&icache_ram_bss_remain_end)
#define ICACHE_GPU_ADDR (void *)(ICACHE_GPU_START)
#define ICACHE_GPU_SIZE (int)(ICACHE_GPU_END - ICACHE_GPU_START)
static struct lbuff_head *dcache_gpu_lbuf = NULL;
static struct lbuff_head *icache_gpu_lbuf = NULL;
#if TCFG_ICACHE_DYNAMIC_SWITCH
extern void icache_way_switch(u8 num);
static void jlgpu_icache_ram_check(void)
{
if (icache_gpu_lbuf == NULL) {
icache_way_switch(4 - TCFG_FREE_ICACHE_WAY);
icache_gpu_lbuf = lbuf_init(ICACHE_GPU_ADDR, ICACHE_GPU_SIZE, 4, 0);
}
}
static u8 jlgpu_icache_ram_enter(u32 timeout)
{
if (icache_gpu_lbuf) {
struct lbuff_state state = {0};
lbuf_state(icache_gpu_lbuf, &state);
if (((int)state.avaliable + (int)sizeof(struct lbuff_head)) == ICACHE_GPU_SIZE) {
icache_gpu_lbuf = NULL;
icache_way_switch(4);
return 1;
} else {
putchar('C');
}
}
return 0;
}
REGISTER_LP_REQUEST(power_jlui_icache) = {
.name = "ich_ram",
.request_enter = jlgpu_icache_ram_enter,
};
#endif
static int jlgpu_cache_init(void)
{
#if TCFG_DCACHE_RUN_GPU_BUF
dcache_gpu_lbuf = lbuf_init(DCACHE_GPU_ADDR, DCACHE_GPU_SIZE, 4, 0);
/* lbuf_dump(dcache_gpu_lbuf); */
#endif
#if TCFG_ICACHE_RUN_GPU_BUF||TCFG_ICACHE_RUN_FTL_BUF
icache_gpu_lbuf = lbuf_init(ICACHE_GPU_ADDR, ICACHE_GPU_SIZE, 4, 0);
/* lbuf_dump(icache_gpu_lbuf); */
#endif
return 0;
}
early_initcall(jlgpu_cache_init);
static int jlgpu_buf_is_cache(void *buf)
{
#if TCFG_DCACHE_RUN_GPU_BUF
if (((int)buf >= DCACHE_GPU_START) && ((int)buf < DCACHE_GPU_END)) {
return true;
}
#endif
#if TCFG_ICACHE_RUN_GPU_BUF||TCFG_ICACHE_RUN_FTL_BUF
if (((int)buf >= ICACHE_GPU_START) && ((int)buf < ICACHE_GPU_END)) {
return true;
}
#endif
return false;
}
static void *jlgpu_cache_malloc(int size)
{
void *ptr = NULL;
#if TCFG_ICACHE_DYNAMIC_SWITCH
jlgpu_icache_ram_check();
#endif
#if TCFG_DCACHE_RUN_GPU_BUF
if (ptr == NULL) {
ptr = lbuf_alloc(dcache_gpu_lbuf, size);
/* if (ptr == NULL) { */
/* printf("dcache gpu over \n"); */
/* lbuf_dump(dcache_gpu_lbuf); */
/* } */
}
#endif
#if TCFG_ICACHE_RUN_GPU_BUF||TCFG_ICACHE_RUN_FTL_BUF
if (ptr == NULL) {
ptr = lbuf_alloc(icache_gpu_lbuf, size);
/* if (ptr == NULL) { */
/* printf("icache gpu over \n"); */
/* lbuf_dump(icache_gpu_lbuf); */
/* } */
}
#endif
return ptr;
}
static void jlgpu_cache_free(void *buf)
{
lbuf_free(buf);
}
void *cache_malloc(int size)
{
void *ptr = jlgpu_cache_malloc(size);
if (ptr == NULL) {
ptr = malloc(size);
}
printf("%s ptr:0x%x\n", __func__, (u32)ptr);
return ptr;
}
void cache_free(void *buf)
{
if (jlgpu_buf_is_cache(buf)) {
jlgpu_cache_free(buf);
return;
}
free(buf);
return;
}
#endif
/***************************************************************/
// PSRAM
/***************************************************************/
#define NO_CACHE_ADDR_BEGIN ((void*)0x04000000)
#define NO_CACHE_ADDR_END ((void*)0x08000000)//不含
#define CACHE_ADDR_BEGIN ((void*)0x08000000)
#define CACHE_ADDR_END ((void*)0x0C000000)//不含
#define CACHE_NO_CACHE_TRANS (0x04000000)
#define PSRAM_ADDR_BEGIN NO_CACHE_ADDR_BEGIN
#define PSRAM_ADDR_END CACHE_ADDR_END
/* ------------------------------------------------------------------------------------*/
/**
* @brief psram_cache_2_nocache
*
* @param p
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
void *psram_cache_2_nocache(void *p)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
if ((p >= CACHE_ADDR_BEGIN) && (p < CACHE_ADDR_END)) {
u32 addr = (u32)p;
return (void *)(addr - CACHE_NO_CACHE_TRANS);
}
if ((p >= NO_CACHE_ADDR_BEGIN) && (p < NO_CACHE_ADDR_END)) {
return p;
}
ASSERT(0, "ADDR:0x%x rets:0x%x", (u32)p, rets);
return NULL;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief psram_nocache_2_cache
*
* @param p
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
void *psram_nocache_2_cache(void *p)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
if ((p >= CACHE_ADDR_BEGIN) && (p < CACHE_ADDR_END)) {
return (p);
}
if ((p >= NO_CACHE_ADDR_BEGIN) && (p < NO_CACHE_ADDR_END)) {
u32 addr = (u32)p;
return (void *)(addr + CACHE_NO_CACHE_TRANS);
}
ASSERT(0, "ADDR:0x%x rets:0x%x", (u32)p, rets);
return NULL;
}
int ui_buf_is_psram_nocache(void *buf)
{
#if TCFG_PSRAM_DEV_ENABLE
if ((buf >= NO_CACHE_ADDR_BEGIN) && (buf < NO_CACHE_ADDR_END)) {
return true;
}
#endif
return false;
}
int ui_buf_is_psram(void *buf)
{
#if TCFG_PSRAM_DEV_ENABLE
if ((buf >= PSRAM_ADDR_BEGIN) && (buf < PSRAM_ADDR_END)) {
return true;
}
#endif
return false;
}
#ifdef UI_BUF_CALC_LITE
static void *jlui_malloc_calc_lite(int size, u32 ram_type, u32 module_type)
{
u8 *buf = NULL;
u8 sram_flag = 0;
size += 8;
do {
#if (TCFG_DCACHE_RUN_GPU_BUF || TCFG_ICACHE_RUN_GPU_BUF)&&(!TCFG_PSRAM_DEV_ENABLE)
if (module_type == UI_MODULE_GPU) {
buf = jlgpu_cache_malloc(size);
if (buf) {
break;
}
}
#endif
#if TCFG_PSRAM_DEV_ENABLE //psram buf
if (config_ui_alloc_psram_mod_sel & BIT((module_type & 0xffff))) {
buf = malloc_psram(size);
if (buf) {
break;
}
}
#endif
buf = malloc(size); //sram buf
sram_flag = 1;
} while (0);
size -= 8;
int magic = 0xaabbccdd;
memcpy(buf, &magic, 4); //free时识别
memcpy(buf + 4, &size, 4); //free时统计
jlui_malloc_total_ram_count += size;
jlui_malloc_total_ram_cnt++;
if (jlui_malloc_total_ram_count > jlui_malloc_total_ram_max) {
jlui_malloc_total_ram_max = jlui_malloc_total_ram_count;
jlui_malloc_total_ram_cnt_max = jlui_malloc_total_ram_cnt;
}
if (sram_flag) {
jlui_malloc_sram_count += size;
jlui_malloc_sram_cnt++;
if (jlui_malloc_sram_count > jlui_malloc_sram_max) {
jlui_malloc_sram_max = jlui_malloc_sram_count;
jlui_malloc_sram_cnt_max = jlui_malloc_sram_cnt;
jlui_malloc_sram_unuse = xPortGetPhysiceMemorySize();
}
}
buf += 8;
return (void *)buf;
}
static void jlui_free_calc_lite(void *buf)
{
int size = 0;
u8 *tmp_buf = (u8 *)buf;
tmp_buf -= 8;
u32 magic = 0;
memcpy(&magic, tmp_buf, 4);
if (magic == 0xaabbccdd) {
memcpy(&size, tmp_buf + 4, 4);
jlui_malloc_total_ram_cnt--;
jlui_malloc_total_ram_count -= size;
buf = tmp_buf;
}
#if (TCFG_DCACHE_RUN_GPU_BUF || TCFG_ICACHE_RUN_GPU_BUF)&&(!TCFG_PSRAM_DEV_ENABLE)
if (jlgpu_buf_is_cache(buf)) {
jlgpu_cache_free(buf);
return;
}
#endif
#if TCFG_PSRAM_DEV_ENABLE
if (ui_buf_is_psram(buf)) {
buf = psram_nocache_2_cache(buf);
free_psram(buf);
return;
}
#endif
if (size) {
jlui_malloc_sram_cnt--;
jlui_malloc_sram_count -= size;
}
free(buf);
}
#endif
static void *jlui_malloc_normal(int size, u32 ram_type, u32 module_type)
{
void *buf = NULL;
do {
#if (TCFG_DCACHE_RUN_GPU_BUF || TCFG_ICACHE_RUN_GPU_BUF)&&(!TCFG_PSRAM_DEV_ENABLE)
if (module_type == UI_MODULE_GPU) {
buf = jlgpu_cache_malloc(size);
if (buf) {
break;
}
}
#endif
#if TCFG_PSRAM_DEV_ENABLE //psram buf
if ((config_ui_alloc_psram_mod_sel & BIT(module_type)) || (ram_type == UI_RAM_PSRAM)) {
buf = malloc_psram(size);
if (buf) {
break;
}
}
#endif
buf = malloc(size); //sram buf
} while (0);
return buf;
}
static void jlui_free_normal(void *buf)
{
#if TCFG_DCACHE_RUN_GPU_BUF || TCFG_ICACHE_RUN_GPU_BUF
if (jlgpu_buf_is_cache(buf)) {
jlgpu_cache_free(buf);
return;
}
#endif
#if TCFG_PSRAM_DEV_ENABLE
if (ui_buf_is_psram(buf)) {
if (ui_buf_is_psram_nocache(buf)) {
buf = psram_nocache_2_cache(buf);
}
free_psram(buf);
return;
}
#endif
if (buf) {
free(buf);
}
}
void async_buffer_free(void *buf)
{
jlui_free_normal(buf);
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief jlui_malloc 杰理UI框架内存申请接口
*
* @Params size 申请内存大小
* @Params ram_type 申请的ram类型
* @Params module_type 发起申请的模块
*
* @return 内存指针
*/
/* ------------------------------------------------------------------------------------*/
void *jlui_malloc(int size, u32 ram_type, u32 module_type)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
#ifdef UI_BUF_CALC_LITE
void *buf = jlui_malloc_calc_lite(size, ram_type, module_type);
#else
void *buf = jlui_malloc_normal(size, ram_type, module_type);
#endif//UI_BUF_CALC_LITE
#ifdef UI_BUF_CALC
ui_buf_calc_add(buf, size, ram_type, module_type);
#endif//UI_BUF_CALC
#ifdef UI_BUF_DEBUG
printf("[%s]buf:0x%x rets:0x%x size:0x%x ram_type:0x%x module_type:0x%x", __func__, (u32)buf, rets, size, ram_type, module_type);
#endif
return (void *)buf;
}
void *jlui_zalloc(int size)
{
void *p = jlui_malloc(size, UI_RAM_SRAM, UI_MODULE_FRAME);
if (p) {
memset(p, 0x00, size);
}
return p;
}
void jlui_free(void *buf, u32 ram_type, u32 module_type)
{
u32 rets;
__asm__ volatile("%0 = rets":"=r"(rets));
#ifdef UI_BUF_DEBUG
printf("[%s]buf:0x%x rets:0x%x ram_type:0x%x module_type:0x%x", __func__, (u32)buf, rets, ram_type, module_type);
#endif
#ifdef UI_BUF_CALC_LITE
jlui_free_calc_lite(buf);
#else
jlui_free_normal(buf);
#endif//UI_BUF_CALC_LITE
#ifdef UI_BUF_CALC
ui_buf_calc_sub(buf, ram_type, module_type);
#endif//UI_BUF_CALC
}
u8 buf_is_heap_addr(void *p)
{
if (memory_in_vtl(p)) {
return true;
}
#if TCFG_DCACHE_RUN_GPU_BUF || TCFG_ICACHE_RUN_GPU_BUF
if (jlgpu_buf_is_cache(p)) {
return true;
}
#endif
#if TCFG_PSRAM_DEV_ENABLE
if (ui_buf_is_psram(p)) {
return true;
}
#endif
return false;
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,508 @@
#include "app_config.h"
#include "jlgpu_driver.h"
#include "res/resfile.h"
#include "res_config.h"
#include "ui_resource.h"
#include "control.h"
#include "font/font_all.h"
#include "font/language_list.h"
#include "res/mem_var.h"
#include "jlui_app/ui_style.h"
#if (defined(CONFIG_UI_STYLE_JL_PUBLIC_MODLS_ENABLE) || defined(CONFIG_UI_STYLE_JL_CSC_PUBLIC_MODLS_ENABLE))
//只读文件系统配置
#if TCFG_SDFILE_INSERT_FLASH_ENABLE
#define UI_MODE_PHY_BASE TCFG_SDFILE_FLASH_DEV_PATY_BASE //分区地址
#define UI_MODE_PHY_FLASH PHY_JL_INSERT_FLASH //分区物理区间
#elif TCFG_SDFILE_EXTERN_FLASH_ENABLE
#define UI_MODE_PHY_BASE TCFG_SDFILE_FLASH_DEV_PATY_BASE //分区地址
#define UI_MODE_PHY_FLASH PHY_JL_EXTERN_FLASH //分区物理区间
#else
#define UI_MODE_PHY_BASE 0
#define UI_MODE_PHY_FLASH PHY_JL_NAND_FLASH
#endif
//vir fat 文件系统
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
//内置flash
#define UI_FAT_PHY_FLASH PHY_JL_INSERT_FLASH
#define UI_FAT_PHY_WATCH_BASE TCFG_VIRFAT_FLASH_DEV_PATY_BASE
#else
//外挂flash
#define UI_FAT_PHY_FLASH PHY_JL_EXTERN_FLASH
#define UI_FAT_PHY_WATCH_BASE 0
#endif
#if TCFG_NANDFLASH_DEV_ENABLE
#define UI_FAT_PHY_BASE TCFG_UI_FAT_FLASH_DEV_PATY_SIZE
#endif
extern u32 sfc1_flash_addr2cpu_addr(u32 offset);
int ui_res_get_image_flash_info(struct flash_file_info *image_info, struct flash_file_info *prj_info, struct image_file *img_file);
int ui_prj_info_table_release();
int ui_watch_resfile_check(void);
//字库设计放内置
struct ui_load_info ui_load_info_table[] = {
#if TCFG_NANDFLASH_DEV_ENABLE&&(!TCFG_SDFILE_INSERT_FLASH_ENABLE)
{0, 0, UI_MODE_PHY_FLASH, UI_MODE_PHY_BASE, JL_PATH"JL.sty", NULL},
#else
{0, 0, UI_MODE_PHY_FLASH, UI_MODE_PHY_BASE, JL_PATH"JL.sty", NULL},
#endif
#if TCFG_NANDFLASH_DEV_ENABLE&&(!TCFG_VIRFAT_INSERT_FLASH_ENABLE)
{1, 0, PHY_JL_NAND_FLASH, UI_FAT_PHY_BASE, RES_PATH"watch/watch.sty", NULL},
#else
{1, 1, UI_FAT_PHY_FLASH, UI_FAT_PHY_WATCH_BASE, RES_PATH"watch/watch.sty", NULL},
#endif
{2, 0, UI_MODE_PHY_FLASH, UI_MODE_PHY_BASE, SIDEBAR_PATH"sidebar.sty", NULL},
{3, 0, UI_MODE_PHY_FLASH, UI_MODE_PHY_BASE, NULL, NULL},
{4, 0, PHY_JL_INSERT_FLASH, 0, UPGRADE_PATH"upgrade.sty", NULL},
{-1, 0, PHY_JL_EXTERN_FLASH, 0, NULL, NULL},
};
#define UI_PRJ_RES_JL BIT(0)
#define UI_PRJ_RES_WATCH BIT(1)
#define UI_PRJ_RES_SIDEBAR BIT(2)
#define UI_PRJ_RES_UPDATE BIT(3)
#define UI_PRJ_RES_CHECK (UI_PRJ_RES_JL|UI_PRJ_RES_WATCH)
/* ------------------------------------------------------------------------------------*/
/**
* @brief ui_res_flash_info_get 获取文件信息
*
* @param file_info 输出,文件信息
* @param path 文件路径
* @param str 不重要,给"res"
* @param mmu_tab 1,返回mmu_tab
*
* @return
*/
/* ------------------------------------------------------------------------------------*/
int ui_res_flash_info_get(struct flash_file_info *file_info, char *path, char *str, int mmu_tab)
{
/* #if TCFG_NANDFLASH_DEV_ENABLE */
/* return 0; */
/* #else */
return __ui_res_flash_info_get(file_info, path, str, ui_load_info_table[1].phy_dev, ui_load_info_table[1].phy_addr, mmu_tab);
/* #endif */
}
int jlui_res_get_image_info(u32 prj_id, u32 img_id, UI_RESFILE *specfile, struct image_file *image, struct flash_file_info *info)
{
int ret = 0;
u32 image_id = img_id;
u32 page_num = img_id >> 16;
/* ret = open_image_by_id(prj_id, specfile, image, (image_id & 0xffff), (image_id >> 16)); */
if (specfile) {
if (open_image_by_id(prj_id, specfile, image, (image_id & 0xffff), (image_id >> 16))) {
printf("open image by id err!\n");
return -EFAULT;
}
} else {
struct mem_var *list;
if ((list = mem_var_search(0, 0, (image_id & 0xffff), page_num, prj_id)) != NULL) {
mem_var_get(list, (u8 *)image, sizeof(struct image_file));
} else {
if (open_image_by_id(prj_id, specfile, image, (image_id & 0xffff), (image_id >> 16))) {
printf("open image by id err!\n");
return -EFAULT;
}
mem_var_add(0, 0, (image_id & 0xffff), page_num, prj_id, (u8 *)image, sizeof(struct image_file));
}
}
/* if (ret) { */
/* printf("open image by id err!\n"); */
/* return ret; */
/* } */
/* printf("open image by id succ!\n"); */
return ret;
}
int jlui_res_get_strpic_info(u32 prj_id, u8 mode, u16 id, struct image_file *image, struct flash_file_info *info)
{
int ret;
u32 str_id = id;
if (mode == 0) {
ret = open_string_pic(prj_id, image, str_id);
} else if (mode == 1) {
ret = open_string_pic2(prj_id, image, str_id);
} else {
ret = -1;
}
if (ret) {
printf("open string err!\n");
return ret;
}
/* printf("open string succ!\n"); */
ui_res_get_image_flash_info(info, &ui_load_info_table[prj_id].str_file_info, image);
return ret;
}
char *ui_get_res_path_by_pj_id(int prj)
{
return (char *)ui_load_info_table[prj].path;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief ui_resfile_check 资源校验
*
* @return 0 成功 other 失败
*
* @note UI_PRJ_RES_CHECK 中配置需要检查的项
*/
/* ------------------------------------------------------------------------------------*/
int ui_resfile_check()
{
#if (UI_PRJ_RES_CHECK & UI_PRJ_RES_JL)
UI_RESFILE *fp_jl = res_fopen(ui_load_info_table[0].path, "r");
if (!fp_jl) {
printf("[%s] ui prj[jl] check fail", __func__);
return -1;
}
res_fclose(fp_jl);
#endif
#if (UI_PRJ_RES_CHECK & UI_PRJ_RES_WATCH)
int ret = ui_watch_resfile_check();
if (ret == false) {
printf("[%s] ui prj[watch] check fail", __func__);
return -1;
}
#endif
#if (UI_PRJ_RES_CHECK & UI_PRJ_RES_SIDEBAR)
UI_RESFILE *fp_sidebar = res_fopen(ui_load_info_table[2].path, "r");
if (!fp_sidebar) {
printf("[%s] ui prj[sidebar] check fail", __func__);
return -1;
}
res_fclose(fp_sidebar);
#endif
#if (UI_PRJ_RES_CHECK & UI_PRJ_RES_UPDATE)
UI_RESFILE *fp_update = res_fopen(ui_load_info_table[4].path, "r");
if (!fp_update) {
printf("[%s] ui prj[update] check fail", __func__);
return -1;
}
res_fclose(fp_update);
#endif
void rcsp_update_flag_clear();
#if TCFG_UPDATE_ENABLE
rcsp_update_flag_clear();
#endif
printf("[%s] ui prj check succ ", __func__);
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief ui_resfile_info_init ui资源信息初始化
*
* @return 0 succ other fail
*/
/* ------------------------------------------------------------------------------------*/
int ui_resfile_info_init(
void *(*malloc)(int size, u32 ram_type, u32 module_type),
void (*free)(void *p, u32 ram_type, u32 module_type))
{
//资源校验
if (ui_resfile_check()) {
#if (RCSP_MODE && JL_RCSP_EXTRA_FLASH_OPT)
extern void rcsp_eflash_flag_set(u8 eflash_state_type);
rcsp_eflash_flag_set(1);//校验失败,进文件传输
#endif
return -1;
}
//注册tab到库
ui_prj_info_table_init(ui_load_info_table, malloc, free);
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief ui_resfile_info_release 注销ui资源
*
* @return 0
*/
/* ------------------------------------------------------------------------------------*/
int ui_resfile_info_release()
{
extern int ui_prj_info_table_release();
ui_prj_info_table_release();
return 0;
}
//**************************************************************************************//
#if 0
void ui_resfile_test_code()
{
struct flash_file_info file_info = {0};
struct flash_file_info image_info = {0};
struct image_file image_f = {0};
ui_resfile_info_init();
int ret = open_image_by_id(0, NULL, &image_f, 1, 1);
if (ret) {
printf("open image file");
return ;
}
ui_res_get_image_flash_info(&image_info, &ui_load_info_table[0].image_file_info, &image_f);
}
#endif
char *font_get_file_addr(char *file_name)
{
struct vfs_attr attr;
FILE *fp = fopen(file_name, "r");
if (!fp) {
printf("Failed to get font file addr!\n");
return NULL;
}
fget_attrs(fp, &attr);
fclose(fp);
#if TCFG_SDFILE_EXTERN_FLASH_ENABLE
return (char *) sfc1_flash_addr2cpu_addr(attr.sclust + UI_MODE_PHY_BASE);
#else
return (char *)sdfile_flash_addr2cpu_addr(attr.sclust + UI_MODE_PHY_BASE);
#endif
}
__attribute__((always_inline))
void __font_pix_copy(struct font_info *info, u8 *pix, s16 x, s16 y, u16 height, u16 width)
{
int i, j, h;
u16 xpos;
u16 ypos;
if (info->flags & FONT_SHOW_SCROLL) {
int font_lang_id = font_lang_get();
if (font_lang_id == Arabic || font_lang_id == Hebrew || font_lang_id == UnicodeMixLeftword) { //显示方向从右到左
if (x > info->text_width - info->xpos_offset) {
return;
}
} else {
if (x + width < info->xpos_offset) { //x + width防止字符被中断
return; //当解析字符串累计buf宽度未到指定位置时不填充字库buf
} else {
x -= info->xpos_offset; //偏移x的值,使其对应到字库buf起始位置
}
}
}
for (j = 0; j < (height + 7) / 8; j++) { /* 纵向8像素为1字节 */
for (i = 0; i < width; i++) {
u8 pixel = pix[j * width + i];
int hh = height - (j * 8);
if (hh > 8) {
hh = 8;
}
if (x + i < 0) {
continue; //x的值在文本框边界的时候可能为负,将负的部分舍弃
}
xpos = x + i;
for (h = 0; h < hh; h++) {
u16 clr = (pixel & BIT(h)) ? 1 : 0;
if (clr) {
if (info->text_image_buf) {
u8 *pdisp = info->text_image_buf;
if (y + j * 8 + h < 0) {
continue;
}
ypos = y + j * 8 + h;
if ((ypos < info->text_image_height) && (xpos < info->text_image_width)) {
pdisp[ypos * info->text_image_stride + xpos / 8] |= BIT(7 - xpos % 8);
} else {
break;
}
}
}
} /* endof for h */
}/* endof for i */
}/* endof for j */
}
__attribute__((always_inline)) //new font tool, for 1 2 4 8 bit
void __new_cb_font_pix_copy(struct font_info *info, u8 *pix, s16 x, s16 y, u16 height, u16 width)
{
if (info->flags & FONT_SHOW_SCROLL) {
int font_lang_id = font_lang_get();
if (font_lang_id == Arabic || font_lang_id == Hebrew || \
font_lang_id == UnicodeMixLeftword) {
if (x > info->text_width - info->xpos_offset) {
return;
}
} else {
if (x + width < info->xpos_offset) { //x + width防止字符被中断
return; //当解析字符串累计buf宽度未到指定位置时不填充字库buf
} else {
x -= info->xpos_offset; //偏移x的值,使其对应到字库buf起始位置
}
}
}
u8 *pdisp = (u8 *)info->text_image_buf;
u8 *pixbuf = (u8 *)pix;
int i, j;
struct rect font_r;
struct rect image_r;
struct rect r;
font_r.left = x;
font_r.top = y;
font_r.width = width;
font_r.height = height;
image_r.left = 0;
image_r.top = 0;
image_r.width = info->text_image_width;
image_r.height = info->text_image_height;
u8 pixel, bpp, bpp_mode;
u32 font_bit, image_bit;
u16 font_byte_idx, font_bit_idx;
u16 image_byte_idx, image_bit_idx;
if (get_rect_cover(&font_r, &image_r, &r)) {
bpp_mode = Font_GetBitDepth();
u16 line_pixel = 0;
if (bpp_mode == BIT_DEPTH_1BPP) {
bpp = 1;
line_pixel = info->text_image_stride * 8;
} else if (bpp_mode == BIT_DEPTH_2BPP) {
line_pixel = info->text_image_stride * 4;
bpp = 2;
} else if (bpp_mode == BIT_DEPTH_4BPP) {
line_pixel = info->text_image_stride * 2;
bpp = 4;
} else {
line_pixel = info->text_image_stride;
bpp = 8;
}
u8 pix_num_in_byte = 8 / bpp;
u8 reserved_bit = 0xff >> (8 - bpp);
int font_bit_row_start, img_bit_row_start;
if (bpp == 1) {
for (j = 0; j < r.height; j++) {
font_bit_row_start = (r.top - font_r.top + j) * width + r.left - font_r.left;
img_bit_row_start = (r.top - image_r.top + j) * line_pixel + r.left - image_r.left;
for (i = 0; i < r.width; i++) {
font_bit = font_bit_row_start + i;
font_byte_idx = font_bit >> 3;
font_bit_idx = font_bit & 7;
image_bit = img_bit_row_start + i;
image_byte_idx = image_bit >> 3;
image_bit_idx = image_bit & 7;
pixel = (pixbuf[font_byte_idx] >> ((7 - font_bit_idx))) & reserved_bit;
pdisp[image_byte_idx] |= (pixel << ((7 - image_bit_idx)));
}
}
} else {
for (j = 0; j < r.height; j++) {
font_bit_row_start = (r.top - font_r.top + j) * width + r.left - font_r.left;
img_bit_row_start = (r.top - image_r.top + j) * line_pixel + r.left - image_r.left;
for (i = 0; i < r.width; i++) {
font_bit = font_bit_row_start + i;
font_byte_idx = font_bit / pix_num_in_byte;
font_bit_idx = font_bit % pix_num_in_byte;
image_bit = img_bit_row_start + i;
image_byte_idx = image_bit / pix_num_in_byte;
image_bit_idx = image_bit % pix_num_in_byte;
pixel = (pixbuf[font_byte_idx] >> ((pix_num_in_byte - 1 - font_bit_idx) * bpp)) & reserved_bit;
pdisp[image_byte_idx] |= (pixel << ((pix_num_in_byte - 1 - image_bit_idx) * bpp));
}
}
}
}
}
void platform_putchar(struct font_info *info, u8 *pixel, u16 width, u16 height, u16 x, u16 y)
{
if (info->each_line_width_info) {
u8 total_line = (u8)(info->each_line_width_info[0]);
u8 curr_line = (u8)((info->each_line_width_info[0] >> 8) + 1);
u16 curr_line_width = info->each_line_width_info[curr_line];
if (total_line > 1 || ((info->flags & FONT_VERTICAL_SCROLL) && info->top_extra_fill < 0)) {
u16 x_offset = (info->text_width - curr_line_width) / 2;
int font_lang_id = font_lang_get();
if (font_lang_id == Arabic || font_lang_id == Hebrew || font_lang_id == UnicodeMixLeftword) {
x -= x_offset;
} else {
x += x_offset;
}
}
}
if ((info->tool_version == 0) || (info->tool_version == 0x0100)) {
__font_pix_copy(info,
pixel,
(s16)x,
(s16)y,
height,
width);
} else {
__new_cb_font_pix_copy(info,
pixel,
(s16)x,
(s16)y,
height,
width);
}
}
const struct font_info font_info_table[] = {
//gb2312
{
.language_id = Chinese_Simplified, //简体中文
.flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE,
.pixel.file.name = (char *)FONT_PATH"F_GB2312.PIX",
.ascpixel.file.name = (char *)FONT_PATH"F_ASCII.PIX",
.tabfile.name = (char *)FONT_PATH"F_GB2312.TAB",
.isgb2312 = true,
.bigendian = false,
.putchar = platform_putchar,
},
{
.language_id = Unicode,
.flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE,
.pixel.file.name = (char *)FONT_PATH"F_UNIC.PIX",
.bigendian = false,
.putchar = platform_putchar,
},
{
.language_id = UnicodeMixRightword,
.flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE,
.pixel.file.name = (char *)FONT_PATH"F_UNIC.PIX",
.bigendian = false,
.putchar = platform_putchar,
},
{
.language_id = UnicodeMixLeftword,
.flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE,
.pixel.file.name = (char *)FONT_PATH"F_UNIC.PIX",
.bigendian = false,
.putchar = platform_putchar,
},
{
.language_id = 0,//不能删
},
};
#endif
@@ -0,0 +1,16 @@
#ifndef __PUBLIC_JLUI_RESOURCE_H__
#define __PUBLIC_JLUI_RESOURCE_H__
#include "gpu_format.h"
int jlui_res_get_image_info(u32 prj_id, u32 img_id, UI_RESFILE *specfile, struct image_file *image, struct flash_file_info *info);
int jlui_res_get_strpic_info(u32 prj_id, u8 mode, u16 id, struct image_file *image, struct flash_file_info *info);
int ui_resfile_check();
int ui_resfile_info_init(
void *(*malloc)(int size, u32 ram_type, u32 module_type),
void (*free)(void *p, u32 ram_type, u32 module_type));
int ui_resfile_info_release();
#endif