LVGL 库提交

This commit is contained in:
2026-08-30 08:57:07 +08:00
parent 26c9098630
commit e2f199c6bf
1056 changed files with 556743 additions and 45 deletions
@@ -0,0 +1,92 @@
/**
* @file lv_draw_buf_g2d.c
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_g2d.h"
#if LV_USE_DRAW_G2D
#include "../../lv_draw_buf_private.h"
#include "g2d.h"
#include "lv_g2d_buf_map.h"
#include "lv_g2d_utils.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void * _buf_malloc(size_t size_bytes, lv_color_format_t color_format);
static void _buf_free(void * buf);
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_buf_g2d_init_handlers(void)
{
lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
handlers->buf_malloc_cb = _buf_malloc;
handlers->buf_free_cb = _buf_free;
handlers->invalidate_cache_cb = _invalidate_cache;
}
/**********************
* STATIC FUNCTIONS
**********************/
static void * _buf_malloc(size_t size_bytes, lv_color_format_t color_format)
{
LV_UNUSED(color_format);
size_bytes += LV_DRAW_BUF_ALIGN - 1;
struct g2d_buf * buf = g2d_alloc(size_bytes, 1);
G2D_ASSERT_MSG(buf, "Failed to alloc buffer.");
g2d_insert_buf_map(buf->buf_vaddr, buf);
return buf->buf_vaddr;
}
static void _buf_free(void * buf)
{
g2d_free_item(buf);
}
static void _invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
{
LV_UNUSED(area);
struct g2d_buf * buf = g2d_search_buf_map(draw_buf->data);
G2D_ASSERT_MSG(buf, "Failed to find buffer in map.");
g2d_cache_op(buf, G2D_CACHE_FLUSH);
}
#endif /*LV_USE_DRAW_G2D*/
+336
View File
@@ -0,0 +1,336 @@
/**
* @file lv_draw_g2d.c
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#include "lv_draw_g2d.h"
#if LV_USE_DRAW_G2D
#include "../../../misc/lv_area_private.h"
#include "g2d.h"
#include "lv_g2d_buf_map.h"
/*********************
* DEFINES
*********************/
#define DRAW_UNIT_ID_G2D 8
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**
* Evaluate a task and set the score and preferred G2D unit.
* Return 1 if task is preferred, 0 otherwise (task is not supported).
*/
static int32_t _g2d_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
/**
* Dispatch a task to the G2D unit.
* Return 1 if task was dispatched, 0 otherwise (task not supported).
*/
static int32_t _g2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
/**
* Delete the G2D draw unit.
*/
static int32_t _g2d_delete(lv_draw_unit_t * draw_unit);
#if LV_USE_G2D_DRAW_THREAD
static void _g2d_render_thread_cb(void * ptr);
#endif
static void _g2d_execute_drawing(lv_draw_task_t * t);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_g2d_init(void)
{
lv_draw_buf_g2d_init_handlers();
lv_draw_g2d_unit_t * draw_g2d_unit = lv_draw_create_unit(sizeof(lv_draw_g2d_unit_t));
draw_g2d_unit->base_unit.evaluate_cb = _g2d_evaluate;
draw_g2d_unit->base_unit.dispatch_cb = _g2d_dispatch;
draw_g2d_unit->base_unit.delete_cb = _g2d_delete;
draw_g2d_unit->base_unit.name = "G2D";
g2d_create_buf_map();
if(g2d_open(&draw_g2d_unit->g2d_handle)) {
LV_LOG_ERROR("g2d_open fail.\n");
}
#if LV_USE_G2D_DRAW_THREAD
lv_draw_sw_thread_dsc_t * thread_dsc = &draw_g2d_unit->thread_dsc;
thread_dsc->idx = 0;
thread_dsc->draw_unit = (void *) draw_g2d_unit;
lv_thread_init(&thread_dsc->thread, "g2ddraw", LV_DRAW_THREAD_PRIO, _g2d_render_thread_cb, LV_DRAW_THREAD_STACK_SIZE,
thread_dsc);
#endif
}
void lv_draw_g2d_deinit(void)
{
g2d_free_buf_map();
}
/**********************
* STATIC FUNCTIONS
**********************/
static inline bool _g2d_dest_cf_supported(lv_color_format_t cf)
{
bool is_cf_supported = false;
switch(cf) {
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
default:
break;
}
return is_cf_supported;
}
static inline bool _g2d_src_cf_supported(lv_draw_unit_t * drawunit, lv_color_format_t cf)
{
bool is_cf_supported = false;
switch(cf) {
case LV_COLOR_FORMAT_ARGB8888:
case LV_COLOR_FORMAT_XRGB8888:
is_cf_supported = true;
break;
case LV_COLOR_FORMAT_RGB565: {
int32_t hw_pxp = 0;
lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)drawunit;
g2d_query_hardware(u->g2d_handle, G2D_HARDWARE_PXP, &hw_pxp);
if(!hw_pxp) {
is_cf_supported = true;
}
}
break;
default:
break;
}
return is_cf_supported;
}
static bool _g2d_draw_img_supported(const lv_draw_image_dsc_t * draw_dsc)
{
bool is_tiled = draw_dsc->tile;
/* Tiled image (repeat image) is currently not supported. */
if(is_tiled)
return false;
bool has_recolor = (draw_dsc->recolor_opa > LV_OPA_MIN);
bool has_rotation = (draw_dsc->rotation != 0);
/* Recolor or rotation are not supported. */
if(has_recolor || has_rotation)
return false;
return true;
}
static int32_t _g2d_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
{
LV_UNUSED(u);
const lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
lv_draw_buf_t * draw_buf = draw_dsc_base->layer->draw_buf;
if(!_g2d_dest_cf_supported(draw_dsc_base->layer->color_format))
return 0;
if(draw_buf && !g2d_search_buf_map(draw_buf->data))
return 0;
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL: {
const lv_draw_fill_dsc_t * draw_dsc = (lv_draw_fill_dsc_t *) t->draw_dsc;
/* Most simple case: just a plain rectangle (no radius, no gradient). */
if((draw_dsc->radius != 0) || (draw_dsc->grad.dir != (lv_grad_dir_t)LV_GRAD_DIR_NONE))
return 0;
if(t->preference_score > 70) {
t->preference_score = 70;
t->preferred_draw_unit_id = DRAW_UNIT_ID_G2D;
}
return 1;
}
case LV_DRAW_TASK_TYPE_IMAGE: {
const lv_draw_image_dsc_t * draw_dsc = (lv_draw_image_dsc_t *) t->draw_dsc;
if(!_g2d_src_cf_supported(u, draw_dsc->header.cf))
return 0;
if(!_g2d_draw_img_supported(draw_dsc))
return 0;
if(t->preference_score > 70) {
t->preference_score = 70;
t->preferred_draw_unit_id = DRAW_UNIT_ID_G2D;
}
return 1;
}
default:
return 0;
}
return 0;
}
static int32_t _g2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
{
lv_draw_g2d_unit_t * draw_g2d_unit = (lv_draw_g2d_unit_t *) draw_unit;
#if LV_USE_OS
lv_draw_sw_thread_dsc_t * thread_dsc = &draw_g2d_unit->thread_dsc;
/* Return immediately if it's busy with draw task. */
if(thread_dsc->task_act)
return 0;
#else
/* Return immediately if it's busy with draw task. */
if(draw_g2d_unit->task_act)
return 0;
#endif
/* Try to get an ready to draw. */
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_G2D);
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_G2D)
return LV_DRAW_UNIT_IDLE;
if(lv_draw_layer_alloc_buf(layer) == NULL)
return LV_DRAW_UNIT_IDLE;
t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
t->draw_unit = draw_unit;
#if LV_USE_G2D_DRAW_THREAD
thread_dsc->task_act = t;
/* Let the render thread work. */
if(thread_dsc->inited)
lv_thread_sync_signal(&thread_dsc->sync);
#else
draw_g2d_unit->task_act = t;
_g2d_execute_drawing(t);
draw_g2d_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
draw_g2d_unit->task_act = NULL;
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
lv_draw_dispatch_request();
#endif
return 1;
}
static int32_t _g2d_delete(lv_draw_unit_t * draw_unit)
{
lv_draw_g2d_unit_t * draw_g2d_unit = (lv_draw_g2d_unit_t *) draw_unit;
lv_result_t res = LV_RESULT_OK;
#if LV_USE_G2D_DRAW_THREAD
lv_draw_sw_thread_dsc_t * thread_dsc = &draw_g2d_unit->thread_dsc;
LV_LOG_INFO("Cancel G2D draw thread.");
thread_dsc->exit_status = true;
if(thread_dsc->inited)
lv_thread_sync_signal(&thread_dsc->sync);
res = lv_thread_delete(&thread_dsc->thread);
#endif
g2d_close(draw_g2d_unit->g2d_handle);
return res;
}
static void _g2d_execute_drawing(lv_draw_task_t * t)
{
lv_layer_t * layer = t->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
/* Invalidate only the drawing area */
lv_draw_buf_invalidate_cache(draw_buf, NULL);
switch(t->type) {
case LV_DRAW_TASK_TYPE_FILL:
lv_draw_g2d_fill(t);
break;
case LV_DRAW_TASK_TYPE_IMAGE:
lv_draw_g2d_img(t);
break;
default:
break;
}
}
#if LV_USE_G2D_DRAW_THREAD
static void _g2d_render_thread_cb(void * ptr)
{
lv_draw_sw_thread_dsc_t * thread_dsc = ptr;
lv_thread_sync_init(&thread_dsc->sync);
thread_dsc->inited = true;
while(1) {
/* Wait for sync if there is no task set. */
while(thread_dsc->task_act == NULL) {
if(thread_dsc->exit_status)
break;
lv_thread_sync_wait(&thread_dsc->sync);
}
if(thread_dsc->exit_status) {
LV_LOG_INFO("Ready to exit G2D draw thread.");
break;
}
_g2d_execute_drawing(thread_dsc->task_act);
/* Signal the ready state to dispatcher. */
thread_dsc->task_act->state = LV_DRAW_TASK_STATE_READY;
/* Cleanup. */
thread_dsc->task_act = NULL;
/* The draw unit is free now. Request a new dispatching as it can get a new task. */
lv_draw_dispatch_request();
}
thread_dsc->inited = false;
lv_thread_sync_delete(&thread_dsc->sync);
LV_LOG_INFO("Exit G2D draw thread.");
}
#endif
#endif /*LV_USE_DRAW_G2D*/
+71
View File
@@ -0,0 +1,71 @@
/**
* @file lv_draw_g2d.h
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_DRAW_G2D_H
#define LV_DRAW_G2D_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_DRAW_G2D
#include "../../sw/lv_draw_sw_private.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
typedef struct lv_draw_g2d_unit {
lv_draw_unit_t base_unit;
#if LV_USE_OS
lv_draw_sw_thread_dsc_t thread_dsc;
#else
lv_draw_task_t * task_act;
#endif
void * g2d_handle;
} lv_draw_g2d_unit_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_draw_g2d_init(void);
void lv_draw_g2d_deinit(void);
void lv_draw_buf_g2d_init_handlers(void);
void lv_draw_g2d_fill(lv_draw_task_t * t);
void lv_draw_g2d_img(lv_draw_task_t * t);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_G2D*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_G2D_H*/
@@ -0,0 +1,178 @@
/**
* @file lv_draw_g2d_fill.c
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_g2d.h"
#if LV_USE_DRAW_G2D
#include <stdlib.h>
#include "g2d.h"
#include "../../../misc/lv_area_private.h"
#include "lv_g2d_buf_map.h"
#include "lv_g2d_utils.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/* Blit simple w/ opa and alpha channel */
static void _g2d_fill(void * g2d_handle, struct g2d_surface * dst_surf);
static void _g2d_fill_with_opa(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf);
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
lv_color_t color, lv_opa_t opa);
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
int32_t stride, lv_color_t color);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_g2d_fill(lv_draw_task_t * t)
{
lv_draw_fill_dsc_t * dsc = t->draw_dsc;
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)t->draw_unit;
lv_layer_t * layer = t->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
lv_area_t * coords = &t->area;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t rel_clip_area;
lv_area_copy(&rel_clip_area, &t->clip_area);
lv_area_move(&rel_clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
if(!lv_area_intersect(&blend_area, &rel_coords, &rel_clip_area))
return; /*Fully clipped, nothing to do*/
/* G2D takes stride in pixels. */
int32_t stride = draw_buf->header.stride / (lv_color_format_get_bpp(draw_buf->header.cf) / 8);
/* Destination buffer */
struct g2d_buf * dst_buf = g2d_search_buf_map(draw_buf->data);
bool has_opa = (dsc->opa < (lv_opa_t)LV_OPA_MAX);
struct g2d_surface dst_surf;
_g2d_set_dst_surf(&dst_surf, dst_buf, &blend_area, stride, dsc->color);
if(has_opa) {
struct g2d_buf * tmp_buf = g2d_alloc(lv_area_get_width(&blend_area) * lv_area_get_height(&blend_area) * sizeof(
lv_color32_t), 1);
G2D_ASSERT_MSG(tmp_buf, "Failed to alloc temporary buffer.");
struct g2d_surface src_surf;
_g2d_set_src_surf(&src_surf, tmp_buf, &blend_area, dsc->color, dsc->opa);
_g2d_fill_with_opa(u->g2d_handle, &dst_surf, &src_surf);
g2d_free(tmp_buf);
}
else {
_g2d_fill(u->g2d_handle, &dst_surf);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
lv_color_t color, lv_opa_t opa)
{
int32_t width = lv_area_get_width(area);
int32_t height = lv_area_get_height(area);
src_surf->format = G2D_RGBA8888;
src_surf->left = 0;
src_surf->top = 0;
src_surf->right = width;
src_surf->bottom = height;
src_surf->stride = width;
src_surf->width = width;
src_surf->height = height;
src_surf->planes[0] = buf->buf_paddr;
src_surf->rot = G2D_ROTATION_0;
src_surf->clrcolor = g2d_rgba_to_u32(color);
src_surf->global_alpha = opa;
src_surf->blendfunc = G2D_ONE | G2D_PRE_MULTIPLIED_ALPHA;
}
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
int32_t stride, lv_color_t color)
{
int32_t width = lv_area_get_width(area);
int32_t height = lv_area_get_height(area);
dst_surf->format = G2D_RGBA8888;
dst_surf->left = area->x1;
dst_surf->top = area->y1;
dst_surf->right = area->x1 + width;
dst_surf->bottom = area->y1 + height;
dst_surf->stride = stride;
dst_surf->width = width;
dst_surf->height = height;
dst_surf->planes[0] = buf->buf_paddr;
dst_surf->rot = G2D_ROTATION_0;
dst_surf->clrcolor = g2d_rgba_to_u32(color);
dst_surf->global_alpha = 0xff;
dst_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA;
}
static void _g2d_fill_with_opa(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf)
{
g2d_clear(g2d_handle, src_surf);
g2d_enable(g2d_handle, G2D_BLEND);
g2d_enable(g2d_handle, G2D_GLOBAL_ALPHA);
g2d_blit(g2d_handle, src_surf, dst_surf);
g2d_finish(g2d_handle);
g2d_disable(g2d_handle, G2D_GLOBAL_ALPHA);
g2d_disable(g2d_handle, G2D_BLEND);
}
static void _g2d_fill(void * g2d_handle, struct g2d_surface * dst_surf)
{
g2d_clear(g2d_handle, dst_surf);
g2d_finish(g2d_handle);
}
#endif /*LV_USE_DRAW_G2D*/
+214
View File
@@ -0,0 +1,214 @@
/**
* @file lv_draw_g2d_img.c
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_g2d.h"
#if LV_USE_DRAW_G2D
#include <stdlib.h>
#include <math.h>
#include "g2d.h"
#include "../../../misc/lv_area_private.h"
#include "lv_g2d_utils.h"
#include "lv_g2d_buf_map.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * data);
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
int32_t stride, lv_color_format_t cf, lv_opa_t opa);
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc);
/* Blit simple w/ opa and alpha channel */
static void _g2d_blit(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_draw_g2d_img(lv_draw_task_t * t)
{
lv_draw_image_dsc_t * dsc = t->draw_dsc;
if(dsc->opa <= (lv_opa_t)LV_OPA_MIN)
return;
lv_draw_g2d_unit_t * u = (lv_draw_g2d_unit_t *)t->draw_unit;
lv_layer_t * layer = t->target_layer;
lv_draw_buf_t * draw_buf = layer->draw_buf;
const lv_image_dsc_t * img_dsc = dsc->src;
lv_area_t * coords = &t->area;
lv_area_t rel_coords;
lv_area_copy(&rel_coords, coords);
lv_area_move(&rel_coords, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t clip_area;
lv_area_copy(&clip_area, &t->clip_area);
lv_area_move(&clip_area, -layer->buf_area.x1, -layer->buf_area.y1);
lv_area_t blend_area;
bool has_transform = (dsc->rotation != 0 || dsc->scale_x != LV_SCALE_NONE || dsc->scale_y != LV_SCALE_NONE);
if(has_transform)
lv_area_copy(&blend_area, &rel_coords);
else if(!lv_area_intersect(&blend_area, &rel_coords, &clip_area))
return; /*Fully clipped, nothing to do*/
lv_area_t src_area;
src_area.x1 = blend_area.x1 - (coords->x1 - layer->buf_area.x1);
src_area.y1 = blend_area.y1 - (coords->y1 - layer->buf_area.y1);
src_area.x2 = src_area.x1 + lv_area_get_width(&blend_area);
src_area.y2 = src_area.y1 + lv_area_get_height(&blend_area);
int32_t src_stride = img_dsc->header.stride / (lv_color_format_get_bpp(img_dsc->header.cf) / 8);
lv_color_format_t src_cf = img_dsc->header.cf;
/* Source image */
struct g2d_buf * src_buf = _g2d_handle_src_buf(img_dsc);
/* Destination buffer */
struct g2d_buf * dst_buf = g2d_search_buf_map(draw_buf->data);
/* G2D takes stride in pixels. */
int32_t dest_stride = draw_buf->header.stride / (lv_color_format_get_bpp(draw_buf->header.cf) / 8);
lv_color_format_t dest_cf = draw_buf->header.cf;
struct g2d_surface src_surf;
struct g2d_surface dst_surf;
_g2d_set_src_surf(&src_surf, src_buf, &src_area, src_stride, src_cf, dsc->opa);
_g2d_set_dst_surf(&dst_surf, dst_buf, &blend_area, dest_stride, dest_cf, dsc);
_g2d_blit(u->g2d_handle, &dst_surf, &src_surf);
}
/**********************
* STATIC FUNCTIONS
**********************/
static struct g2d_buf * _g2d_handle_src_buf(const lv_image_dsc_t * img_dsc)
{
struct g2d_buf * src_buf = g2d_search_buf_map((void *)img_dsc->data);
if(src_buf == NULL) {
src_buf = g2d_alloc(img_dsc->data_size, 1);
G2D_ASSERT_MSG(src_buf, "Failed to alloc source buffer.");
memcpy((uint8_t *)src_buf->buf_vaddr, img_dsc->data, img_dsc->data_size);
g2d_cache_op(src_buf, G2D_CACHE_FLUSH);
g2d_insert_buf_map((void *)img_dsc->data, src_buf);
}
return src_buf;
}
static void _g2d_set_src_surf(struct g2d_surface * src_surf, struct g2d_buf * buf, const lv_area_t * area,
int32_t stride, lv_color_format_t cf, lv_opa_t opa)
{
src_surf->format = g2d_get_buf_format(cf);
src_surf->left = area->x1;
src_surf->top = area->y1;
src_surf->right = area->x2;
src_surf->bottom = area->y2;
src_surf->stride = stride;
src_surf->width = area->x2 - area->x1;
src_surf->height = area->y2 - area->y1;
src_surf->planes[0] = buf->buf_paddr;
src_surf->rot = G2D_ROTATION_0;
src_surf->clrcolor = g2d_rgba_to_u32(lv_color_black());
src_surf->global_alpha = opa;
src_surf->blendfunc = G2D_ONE | G2D_PRE_MULTIPLIED_ALPHA;
}
static void _g2d_set_dst_surf(struct g2d_surface * dst_surf, struct g2d_buf * buf, const lv_area_t * area,
int32_t stride, lv_color_format_t cf, const lv_draw_image_dsc_t * dsc)
{
int32_t width = lv_area_get_width(area);
int32_t height = lv_area_get_height(area);
lv_point_t pivot = dsc->pivot;
/*The offsets are now relative to the transformation result with pivot ULC*/
int32_t piv_offset_x = 0;
int32_t piv_offset_y = 0;
int32_t trim_x = 0;
int32_t trim_y = 0;
int32_t dest_w;
int32_t dest_h;
float fp_scale_x = (float)dsc->scale_x / LV_SCALE_NONE;
float fp_scale_y = (float)dsc->scale_y / LV_SCALE_NONE;
int32_t int_scale_x = (int32_t)fp_scale_x;
int32_t int_scale_y = (int32_t)fp_scale_y;
/*Any scale_factor in (k, k + 1] will result in a trim equal to k*/
trim_x = (fp_scale_x == int_scale_x) ? int_scale_x - 1 : int_scale_x;
trim_y = (fp_scale_y == int_scale_y) ? int_scale_y - 1 : int_scale_y;
dest_w = width * fp_scale_x + trim_x;
dest_h = height * fp_scale_y + trim_y;
/*Final pivot offset = scale_factor * rotation_pivot_offset + scaling_pivot_offset*/
piv_offset_x = floor(fp_scale_x * piv_offset_x) - floor((fp_scale_x - 1) * pivot.x);
piv_offset_y = floor(fp_scale_y * piv_offset_y) - floor((fp_scale_y - 1) * pivot.y);
dst_surf->format = g2d_get_buf_format(cf);
dst_surf->left = area->x1 + piv_offset_x;
dst_surf->top = area->y1 + piv_offset_y;
dst_surf->right = area->x1 + piv_offset_x + dest_w - trim_x;
dst_surf->bottom = area->y1 + piv_offset_y + dest_h - trim_y;
dst_surf->stride = stride;
dst_surf->width = dest_w - trim_x;
dst_surf->height = dest_h - trim_y;
dst_surf->planes[0] = buf->buf_paddr;
dst_surf->rot = G2D_ROTATION_0;
dst_surf->clrcolor = g2d_rgba_to_u32(lv_color_black());
dst_surf->global_alpha = 0xff;
dst_surf->blendfunc = G2D_ONE_MINUS_SRC_ALPHA | G2D_PRE_MULTIPLIED_ALPHA;
}
static void _g2d_blit(void * g2d_handle, struct g2d_surface * dst_surf, struct g2d_surface * src_surf)
{
g2d_enable(g2d_handle, G2D_BLEND);
g2d_enable(g2d_handle, G2D_GLOBAL_ALPHA);
g2d_blit(g2d_handle, src_surf, dst_surf);
g2d_finish(g2d_handle);
g2d_disable(g2d_handle, G2D_GLOBAL_ALPHA);
g2d_disable(g2d_handle, G2D_BLEND);
}
#endif /*LV_USE_DRAW_G2D*/
+247
View File
@@ -0,0 +1,247 @@
/**
* @file lv_g2d_buf_map.c
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#include "lv_g2d_buf_map.h"
#if LV_USE_DRAW_G2D
#include <stdio.h>
#include "lv_g2d_utils.h"
#include "g2d.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static unsigned long _map_hash_function(void * ptr);
static lv_map_item_t * _map_create_item(void * key, struct g2d_buf * value);
static void _map_free_item(lv_map_item_t * item);
static void _handle_collision(unsigned long index, lv_map_item_t * item);
/**********************
* STATIC VARIABLES
**********************/
static lv_buf_map_t * table;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void g2d_create_buf_map(void)
{
table = (lv_buf_map_t *) lv_malloc(sizeof(lv_buf_map_t));
table->size = LV_G2D_HASH_TABLE_SIZE;
table->count = 0;
table->items = (lv_map_item_t **) lv_malloc_zeroed(table->size * sizeof(lv_map_item_t *));
table->overflow_list = (lv_array_t **) lv_malloc_zeroed(table->size * sizeof(lv_array_t *));
}
void g2d_free_buf_map(void)
{
for(int i = 0; i < table->size; i++) {
if(table->overflow_list[i]) {
lv_array_deinit(table->overflow_list[i]);
lv_free(table->overflow_list[i]);
}
lv_map_item_t * item = table->items[i];
if(item != NULL)
_map_free_item(item);
}
lv_free(table->items);
lv_free(table->overflow_list);
lv_free(table);
}
void g2d_insert_buf_map(void * key, struct g2d_buf * value)
{
lv_map_item_t * item = _map_create_item(key, value);
int index = _map_hash_function(key);
if(table->items[index] == NULL) {
/* Key not found. */
if(table->count == table->size) {
/* Table is full. */
_map_free_item(item);
G2D_ASSERT_MSG(false, "Hash table is full.");
return;
}
}
else {
if(table->items[index]->key == key) {
/* Key already exists, update value. */
table->items[index]->value = value;
return;
}
else {
/* Handle the collision */
_handle_collision(index, item);
return;
}
}
/* Insert item. */
table->items[index] = item;
table->count++;
}
struct g2d_buf * g2d_search_buf_map(void * key)
{
int index = _map_hash_function(key);
lv_map_item_t * item = table->items[index];
lv_array_t * list = (lv_array_t *)table->overflow_list[index];
if(item == NULL)
return NULL;
if(item->key == key)
return item->value;
if(list == NULL)
return NULL;
for(uint32_t i = 0; i < lv_array_size(list); i++) {
item = (lv_map_item_t *)lv_array_at(list, i);
if(item->key == key)
return item->value;
}
return NULL;
}
void g2d_free_item(void * key)
{
/* Delete an item from the table. */
int index = _map_hash_function(key);
lv_map_item_t * item = table->items[index];
lv_array_t * list = (lv_array_t *)table->overflow_list[index];
if(item == NULL) {
return;
}
else if(list == NULL && item->key == key) {
/* No collision chain, just remove item. */
table->items[index] = NULL;
_map_free_item(item);
table->count--;
return;
}
else if(list != NULL) {
/* Collision chain exists. */
for(uint32_t i = 0; i < lv_array_size(list); i++) {
item = (lv_map_item_t *)lv_array_at(list, i);
if(item->key == key) {
lv_array_remove(list, i);
return;
}
}
}
}
void g2d_print_table(void)
{
LV_LOG("\nHash Table\n-------------------\n");
for(int i = 0; i < table->size; i++) {
if(table->items[i]) {
LV_LOG("Index:%d, Key:%p, Value:%p\n", i, table->items[i] -> key, (void *)table->items[i]->value);
if(table->overflow_list[i]) {
for(uint32_t j = 0 ; j < lv_array_size(table->overflow_list[i]); j++) {
lv_map_item_t * item = (lv_map_item_t *)lv_array_at(table->overflow_list[i], j);
LV_LOG("Index:%d, Key:%p, Value:%p\n", i, item -> key, (void *)item->value);
}
}
}
}
LV_LOG("-------------------\n\n");
}
/**********************
* STATIC FUNCTIONS
**********************/
static unsigned long _map_hash_function(void * ptr)
{
unsigned long i = 0;
char str[64];
G2D_ASSERT_MSG(ptr, "Key is null.");
sprintf(str, "%p", ptr);
for(int j = 0; str[j]; j++)
i += str[j];
return i % LV_G2D_HASH_TABLE_SIZE;
}
static void _handle_collision(unsigned long index, lv_map_item_t * item)
{
if(table->overflow_list[index] == NULL) {
/* Create the list. */
lv_array_t * list = (lv_array_t *) lv_malloc(sizeof(lv_array_t));;
lv_array_init(list, LV_ARRAY_DEFAULT_CAPACITY, sizeof(lv_map_item_t));
lv_array_push_back(list, item);
table->overflow_list[index] = list;
return;
}
else {
lv_array_t * list = (lv_array_t *)table->overflow_list[index];
for(uint32_t i = 0; i < lv_array_size(list); i++) {
lv_map_item_t * it = (lv_map_item_t *)lv_array_at(list, i);
if(it->key == item->key) {
/* Key exists, update value. */
it->value = item->value;
return;
}
}
/* Insert to the list. */
lv_array_push_back(table->overflow_list[index], item);
return;
}
}
static lv_map_item_t * _map_create_item(void * key, struct g2d_buf * value)
{
lv_map_item_t * item = (lv_map_item_t *) lv_malloc(sizeof(lv_map_item_t));
G2D_ASSERT_MSG(item, "Failed to alloc item.");
item->key = key;
item->value = value;
return item;
}
static void _map_free_item(lv_map_item_t * item)
{
/* Also free the g2d_buf. */
g2d_free(item->value);
item->key = NULL;
item->value = NULL;
lv_free(item);
item = NULL;
}
#endif /*LV_USE_DRAW_G2D*/
@@ -0,0 +1,81 @@
/**
* @file lv_g2d_buf_map.h
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_G2D_BUF_MAP_H
#define LV_G2D_BUF_MAP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_DRAW_G2D
#include "../../../misc/lv_array.h"
#include <string.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/* Map item definition. */
typedef struct lv_map_item {
/* Virtual address buffer. */
void * key;
struct g2d_buf * value;
} lv_map_item_t;
/*Buf map definition. */
typedef struct lv_buf_map {
lv_map_item_t ** items;
lv_array_t ** overflow_list;
int size;
int count;
} lv_buf_map_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
void g2d_create_buf_map(void);
void g2d_free_buf_map(void);
void g2d_insert_buf_map(void * key, struct g2d_buf * value);
struct g2d_buf * g2d_search_buf_map(void * key);
void g2d_free_item(void * key);
void g2d_print_table(void);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_G2D*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* LV_G2D_BUF_MAP_H */
+97
View File
@@ -0,0 +1,97 @@
/**
* @file lv_g2d_utils.c
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
/*********************
* INCLUDES
*********************/
#include "lv_g2d_utils.h"
#if LV_USE_DRAW_G2D
#include "lv_g2d_buf_map.h"
#include "lv_draw_g2d.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
g2d_format_t g2d_get_buf_format(lv_color_format_t cf)
{
g2d_format_t color_f = G2D_RGB565;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
color_f = G2D_RGB565;
break;
case LV_COLOR_FORMAT_ARGB8888:
color_f = G2D_BGRA8888;
break;
case LV_COLOR_FORMAT_XRGB8888:
color_f = G2D_BGRX8888;
break;
case LV_COLOR_FORMAT_RGB888:
color_f = G2D_BGR888;
break;
case LV_COLOR_FORMAT_NV12:
color_f = G2D_NV12;
break;
case LV_COLOR_FORMAT_I420:
color_f = G2D_I420;
break;
case LV_COLOR_FORMAT_NV21:
color_f = G2D_NV21;
break;
case LV_COLOR_FORMAT_YUY2:
color_f = G2D_YUYV;
break;
case LV_COLOR_FORMAT_UYVY:
color_f = G2D_UYVY;
break;
default:
G2D_ASSERT_MSG(false, "Unsupported color format.");
break;
}
return color_f;
}
uint32_t g2d_rgba_to_u32(lv_color_t color)
{
return (uint32_t)((color.red) + (color.green << 8) + (color.blue << 16) + ((uint32_t)0xff << 24));
}
int32_t g2d_get_buf_fd(const lv_draw_buf_t * draw_buf)
{
struct g2d_buf * buf = g2d_search_buf_map(draw_buf->data);
G2D_ASSERT_MSG(buf, "Failed to find buffer in map.");
return g2d_buf_export_fd(buf);
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_DRAW_G2D*/
+72
View File
@@ -0,0 +1,72 @@
/**
* @file lv_g2d_utils.h
*
*/
/**
* Copyright 2024 NXP
*
* SPDX-License-Identifier: MIT
*/
#ifndef LV_G2D_UTILS_H
#define LV_G2D_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_DRAW_G2D
#include "../../sw/lv_draw_sw_private.h"
#include "g2d.h"
#include "g2dExt.h"
/*********************
* DEFINES
*********************/
#if LV_USE_G2D_ASSERT
#define G2D_ASSERT(expr) LV_ASSERT(expr)
#else
#define G2D_ASSERT(expr)
#endif
#define G2D_ASSERT_MSG(expr, msg) \
do { \
if(!(expr)) { \
LV_LOG_ERROR(msg); \
G2D_ASSERT(false); \
} \
} while(0)
/**********************
* TYPEDEFS
**********************/
typedef enum g2d_format g2d_format_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
g2d_format_t g2d_get_buf_format(lv_color_format_t cf);
uint32_t g2d_rgba_to_u32(lv_color_t color);
int32_t g2d_get_buf_fd(const lv_draw_buf_t * draw_buf);
/**********************
* MACROS
**********************/
#endif /*LV_USE_DRAW_G2D*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_G2D_UTILS_H*/