LVGL 库提交
This commit is contained in:
@@ -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*/
|
||||
@@ -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*/
|
||||
@@ -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*/
|
||||
@@ -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*/
|
||||
@@ -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 */
|
||||
@@ -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*/
|
||||
@@ -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*/
|
||||
Reference in New Issue
Block a user