Files
lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.c
nicusorcitu d87737612a perf(pxp, vglite): improve performance and add more features (#4222)
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com>
Signed-off-by: Stefan Babatie <stefan.babatie@nxp.com>
Signed-off-by: Jason Yu <zejiang.yu@nxp.com>
Co-authored-by: Stefan Babatie <stefan.babatie@nxp.com>
Co-authored-by: Jason Yu <zejiang.yu@nxp.com>
2023-05-18 22:43:19 +02:00

574 lines
23 KiB
C

/**
* @file lv_draw_pxp_blend.c
*
*/
/**
* MIT License
*
* Copyright 2020-2023 NXP
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next paragraph)
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_draw_pxp_blend.h"
#if LV_USE_GPU_NXP_PXP
#include "lvgl_support.h"
/*********************
* DEFINES
*********************/
#if LV_COLOR_16_SWAP
#error Color swap not implemented. Disable LV_COLOR_16_SWAP feature.
#endif
#if LV_COLOR_DEPTH == 16
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatRGB565
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatRGB565
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB565
#define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 2U
#elif LV_COLOR_DEPTH == 32
#define PXP_OUT_PIXEL_FORMAT kPXP_OutputPixelFormatARGB8888
#define PXP_AS_PIXEL_FORMAT kPXP_AsPixelFormatARGB8888
#if (!(defined(FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT) && FSL_FEATURE_PXP_HAS_NO_EXTEND_PIXEL_FORMAT)) && \
(!(defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3))
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatARGB8888
#else
#define PXP_PS_PIXEL_FORMAT kPXP_PsPixelFormatRGB888
#endif
#define PXP_TEMP_BUF_SIZE LCD_WIDTH * LCD_HEIGHT * 4U
#elif
#error Only 16bit and 32bit color depth are supported. Set LV_COLOR_DEPTH to 16 or 32.
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static LV_ATTRIBUTE_MEM_ALIGN uint8_t temp_buf[PXP_TEMP_BUF_SIZE];
/**
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
* with combination of transformation (rotation, scale, recolor) and opacity, alpha channel
* or color keying. This requires two steps. First step is used for transformation into
* a temporary buffer and the second one will handle the color format or opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
* with transformation and full opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**
* BLock Image Transfer - copy rectangular image from src buffer to dst buffer
* without transformation but handling color format or opacity.
*
* @param[in/out] dest_buf Destination buffer
* @param[in] dest_area Area with relative coordinates of destination buffer
* @param[in] dest_stride Stride of destination buffer in pixels
* @param[in] src_buf Source buffer
* @param[in] src_area Area with relative coordinates of source buffer
* @param[in] src_stride Stride of source buffer in pixels
* @param[in] dsc Image descriptor
* @param[in] cf Color format
*/
static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_gpu_nxp_pxp_fill(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
lv_color_t color, lv_opa_t opa)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_gpu_nxp_pxp_reset();
/*OUT buffer configure*/
pxp_output_buffer_config_t outputConfig = {
.pixelFormat = PXP_OUT_PIXEL_FORMAT,
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.buffer1Addr = (uint32_t)NULL,
.pitchBytes = dest_stride * sizeof(lv_color_t),
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputConfig);
if(opa >= (lv_opa_t)LV_OPA_MAX) {
/*Simple color fill without opacity - AS disabled*/
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
}
else {
/*Fill with opacity - AS used as source (same as OUT)*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)outputConfig.buffer0Addr,
.pitchBytes = outputConfig.pitchBytes
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
/*Disable PS, use as color generator*/
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(color));
/**
* Configure Porter-Duff blending - src settings are unused for fill without opacity (opa = 0xff).
*
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
* srcFactorMode is actually applied on PS alpha value
* dstFactorMode is actually applied on AS alpha value
*/
pxp_porter_duff_config_t pdConfig = {
.enable = 1,
.dstColorMode = kPXP_PorterDuffColorNoAlpha,
.srcColorMode = kPXP_PorterDuffColorNoAlpha,
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
.srcGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
.dstFactorMode = kPXP_PorterDuffFactorStraight,
.srcFactorMode = (opa >= (lv_opa_t)LV_OPA_MAX) ? kPXP_PorterDuffFactorStraight : kPXP_PorterDuffFactorInversed,
.dstGlobalAlpha = opa,
.srcGlobalAlpha = opa,
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
.srcAlphaMode = kPXP_PorterDuffAlphaStraight /*don't care*/
};
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
lv_gpu_nxp_pxp_run();
}
void lv_gpu_nxp_pxp_blit(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
lv_opa_t opa, lv_disp_rot_t angle)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_coord_t src_w = lv_area_get_width(src_area);
lv_coord_t src_h = lv_area_get_height(src_area);
lv_gpu_nxp_pxp_reset();
/* convert rotation angle */
pxp_rotate_degree_t pxp_rot;
switch(angle) {
case LV_DISP_ROT_NONE:
pxp_rot = kPXP_Rotate0;
break;
case LV_DISP_ROT_90:
pxp_rot = kPXP_Rotate90;
break;
case LV_DISP_ROT_180:
pxp_rot = kPXP_Rotate180;
break;
case LV_DISP_ROT_270:
pxp_rot = kPXP_Rotate270;
break;
default:
pxp_rot = kPXP_Rotate0;
break;
}
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_rot, kPXP_FlipDisable);
pxp_as_blend_config_t asBlendConfig = {
.alpha = opa,
.invertAlpha = false,
.alphaMode = kPXP_AlphaRop,
.ropMode = kPXP_RopMergeAs
};
if(opa >= (lv_opa_t)LV_OPA_MAX) {
/*Simple blit, no effect - Disable PS buffer*/
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
}
else {
pxp_ps_buffer_config_t psBufferConfig = {
.pixelFormat = PXP_PS_PIXEL_FORMAT,
.swapByte = false,
.bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.bufferAddrU = 0U,
.bufferAddrV = 0U,
.pitchBytes = dest_stride * sizeof(lv_color_t)
};
asBlendConfig.alphaMode = kPXP_AlphaOverride;
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
.pitchBytes = src_stride * sizeof(lv_color_t)
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, false);
/*Output buffer.*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT,
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride * sizeof(lv_color_t),
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
lv_gpu_nxp_pxp_run();
}
void lv_gpu_nxp_pxp_blit_transform(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool has_rotation = (dsc->angle != 0);
if(has_recolor || has_rotation) {
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_has_alpha(cf) && !lv_img_cf_is_chroma_keyed(cf)) {
lv_pxp_blit_cover(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
return;
}
else {
/*Recolor and/or rotation with alpha or opacity is done in two steps.*/
lv_pxp_blit_opa(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
return;
}
}
lv_pxp_blit_cf(dest_buf, dest_area, dest_stride, src_buf, src_area, src_stride, dsc, cf);
}
void lv_gpu_nxp_pxp_buffer_copy(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride)
{
lv_coord_t src_width = lv_area_get_width(src_area);
lv_coord_t src_height = lv_area_get_height(src_area);
lv_gpu_nxp_pxp_reset();
const pxp_pic_copy_config_t picCopyConfig = {
.srcPicBaseAddr = (uint32_t)src_buf,
.srcPitchBytes = src_stride * sizeof(lv_color_t),
.srcOffsetX = src_area->x1,
.srcOffsetY = src_area->y1,
.destPicBaseAddr = (uint32_t)dest_buf,
.destPitchBytes = dest_stride * sizeof(lv_color_t),
.destOffsetX = dest_area->x1,
.destOffsetY = dest_area->y1,
.width = src_width,
.height = src_height,
.pixelFormat = PXP_AS_PIXEL_FORMAT
};
PXP_StartPictureCopy(LV_GPU_NXP_PXP_ID, &picCopyConfig);
lv_gpu_nxp_pxp_wait();
}
/**********************
* STATIC FUNCTIONS
**********************/
static void lv_pxp_blit_opa(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
lv_area_t temp_area;
lv_area_copy(&temp_area, dest_area);
lv_coord_t temp_stride = dest_stride;
lv_coord_t temp_w = lv_area_get_width(&temp_area);
lv_coord_t temp_h = lv_area_get_height(&temp_area);
/*Step 1: Transform with full opacity to temporary buffer*/
lv_pxp_blit_cover((lv_color_t *)temp_buf, &temp_area, temp_stride, src_buf, src_area, src_stride, dsc, cf);
/*Switch width and height if angle requires it*/
if(dsc->angle == 900 || dsc->angle == 2700) {
temp_area.x2 = temp_area.x1 + temp_h - 1;
temp_area.y2 = temp_area.y1 + temp_w - 1;
}
/*Step 2: Blit temporary result with required opacity to output*/
lv_pxp_blit_cf(dest_buf, &temp_area, dest_stride, (lv_color_t *)temp_buf, &temp_area, temp_stride, dsc, cf);
}
static void lv_pxp_blit_cover(lv_color_t * dest_buf, lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_coord_t src_w = lv_area_get_width(src_area);
lv_coord_t src_h = lv_area_get_height(src_area);
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
bool has_rotation = (dsc->angle != 0);
lv_point_t pivot = dsc->pivot;
lv_coord_t piv_offset_x;
lv_coord_t piv_offset_y;
lv_gpu_nxp_pxp_reset();
if(has_rotation) {
/*Convert rotation angle and calculate offsets caused by pivot*/
pxp_rotate_degree_t pxp_angle;
switch(dsc->angle) {
case 0:
pxp_angle = kPXP_Rotate0;
piv_offset_x = 0;
piv_offset_y = 0;
break;
case 900:
piv_offset_x = pivot.x + pivot.y - dest_h;
piv_offset_y = pivot.y - pivot.x;
pxp_angle = kPXP_Rotate90;
break;
case 1800:
piv_offset_x = 2 * pivot.x - dest_w;
piv_offset_y = 2 * pivot.y - dest_h;
pxp_angle = kPXP_Rotate180;
break;
case 2700:
piv_offset_x = pivot.x - pivot.y;
piv_offset_y = pivot.x + pivot.y - dest_w;
pxp_angle = kPXP_Rotate270;
break;
default:
piv_offset_x = 0;
piv_offset_y = 0;
pxp_angle = kPXP_Rotate0;
}
PXP_SetRotateConfig(LV_GPU_NXP_PXP_ID, kPXP_RotateOutputBuffer, pxp_angle, kPXP_FlipDisable);
lv_area_move(dest_area, piv_offset_x, piv_offset_y);
}
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
.pitchBytes = src_stride * sizeof(lv_color_t)
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
/*Disable PS buffer*/
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
if(has_recolor)
/*Use as color generator*/
PXP_SetProcessSurfaceBackGroundColor(LV_GPU_NXP_PXP_ID, lv_color_to32(dsc->recolor));
/*Output buffer*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT,
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride * sizeof(lv_color_t),
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
if(has_recolor || lv_img_cf_has_alpha(cf)) {
/**
* Configure Porter-Duff blending.
*
* Note: srcFactorMode and dstFactorMode are inverted in fsl_pxp.h:
* srcFactorMode is actually applied on PS alpha value
* dstFactorMode is actually applied on AS alpha value
*/
pxp_porter_duff_config_t pdConfig = {
.enable = 1,
.dstColorMode = kPXP_PorterDuffColorWithAlpha,
.srcColorMode = kPXP_PorterDuffColorNoAlpha,
.dstGlobalAlphaMode = kPXP_PorterDuffGlobalAlpha,
.srcGlobalAlphaMode = lv_img_cf_has_alpha(cf) ? kPXP_PorterDuffLocalAlpha : kPXP_PorterDuffGlobalAlpha,
.dstFactorMode = kPXP_PorterDuffFactorStraight,
.srcFactorMode = kPXP_PorterDuffFactorInversed,
.dstGlobalAlpha = has_recolor ? dsc->recolor_opa : 0x00,
.srcGlobalAlpha = 0xff,
.dstAlphaMode = kPXP_PorterDuffAlphaStraight, /*don't care*/
.srcAlphaMode = kPXP_PorterDuffAlphaStraight
};
PXP_SetPorterDuffConfig(LV_GPU_NXP_PXP_ID, &pdConfig);
}
lv_gpu_nxp_pxp_run();
}
static void lv_pxp_blit_cf(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,
const lv_color_t * src_buf, const lv_area_t * src_area, lv_coord_t src_stride,
const lv_draw_img_dsc_t * dsc, lv_img_cf_t cf)
{
lv_coord_t dest_w = lv_area_get_width(dest_area);
lv_coord_t dest_h = lv_area_get_height(dest_area);
lv_coord_t src_w = lv_area_get_width(src_area);
lv_coord_t src_h = lv_area_get_height(src_area);
lv_gpu_nxp_pxp_reset();
pxp_as_blend_config_t asBlendConfig = {
.alpha = dsc->opa,
.invertAlpha = false,
.alphaMode = kPXP_AlphaRop,
.ropMode = kPXP_RopMergeAs
};
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX && !lv_img_cf_is_chroma_keyed(cf) && !lv_img_cf_has_alpha(cf)) {
/*Simple blit, no effect - Disable PS buffer*/
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0xFFFFU, 0xFFFFU, 0U, 0U);
}
else {
/*PS must be enabled to fetch background pixels.
PS and OUT buffers are the same, blend will be done in-place*/
pxp_ps_buffer_config_t psBufferConfig = {
.pixelFormat = PXP_PS_PIXEL_FORMAT,
.swapByte = false,
.bufferAddr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.bufferAddrU = 0U,
.bufferAddrV = 0U,
.pitchBytes = dest_stride * sizeof(lv_color_t)
};
if(dsc->opa >= (lv_opa_t)LV_OPA_MAX) {
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaEmbedded : kPXP_AlphaOverride;
}
else {
asBlendConfig.alphaMode = lv_img_cf_has_alpha(cf) ? kPXP_AlphaMultiply : kPXP_AlphaOverride;
}
PXP_SetProcessSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &psBufferConfig);
PXP_SetProcessSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, dest_w - 1U, dest_h - 1U);
}
/*AS buffer - source image*/
pxp_as_buffer_config_t asBufferConfig = {
.pixelFormat = PXP_AS_PIXEL_FORMAT,
.bufferAddr = (uint32_t)(src_buf + src_stride * src_area->y1 + src_area->x1),
.pitchBytes = src_stride * sizeof(lv_color_t)
};
PXP_SetAlphaSurfaceBufferConfig(LV_GPU_NXP_PXP_ID, &asBufferConfig);
PXP_SetAlphaSurfacePosition(LV_GPU_NXP_PXP_ID, 0U, 0U, src_w - 1U, src_h - 1U);
PXP_SetAlphaSurfaceBlendConfig(LV_GPU_NXP_PXP_ID, &asBlendConfig);
if(lv_img_cf_is_chroma_keyed(cf)) {
lv_color_t colorKeyLow = LV_COLOR_CHROMA_KEY;
lv_color_t colorKeyHigh = LV_COLOR_CHROMA_KEY;
bool has_recolor = (dsc->recolor_opa != LV_OPA_TRANSP);
if(has_recolor) {
/* New color key after recoloring */
lv_color_t colorKey = lv_color_mix(dsc->recolor, LV_COLOR_CHROMA_KEY, dsc->recolor_opa);
LV_COLOR_SET_R(colorKeyLow, colorKey.ch.red != 0 ? colorKey.ch.red - 1 : 0);
LV_COLOR_SET_G(colorKeyLow, colorKey.ch.green != 0 ? colorKey.ch.green - 1 : 0);
LV_COLOR_SET_B(colorKeyLow, colorKey.ch.blue != 0 ? colorKey.ch.blue - 1 : 0);
#if LV_COLOR_DEPTH == 16
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0x1f ? colorKey.ch.red + 1 : 0x1f);
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0x3f ? colorKey.ch.green + 1 : 0x3f);
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0x1f ? colorKey.ch.blue + 1 : 0x1f);
#else /*LV_COLOR_DEPTH == 32*/
LV_COLOR_SET_R(colorKeyHigh, colorKey.ch.red != 0xff ? colorKey.ch.red + 1 : 0xff);
LV_COLOR_SET_G(colorKeyHigh, colorKey.ch.green != 0xff ? colorKey.ch.green + 1 : 0xff);
LV_COLOR_SET_B(colorKeyHigh, colorKey.ch.blue != 0xff ? colorKey.ch.blue + 1 : 0xff);
#endif
}
PXP_SetAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_color_to32(colorKeyLow),
lv_color_to32(colorKeyHigh));
}
PXP_EnableAlphaSurfaceOverlayColorKey(LV_GPU_NXP_PXP_ID, lv_img_cf_is_chroma_keyed(cf));
/*Output buffer.*/
pxp_output_buffer_config_t outputBufferConfig = {
.pixelFormat = (pxp_output_pixel_format_t)PXP_OUT_PIXEL_FORMAT,
.interlacedMode = kPXP_OutputProgressive,
.buffer0Addr = (uint32_t)(dest_buf + dest_stride * dest_area->y1 + dest_area->x1),
.buffer1Addr = (uint32_t)0U,
.pitchBytes = dest_stride * sizeof(lv_color_t),
.width = dest_w,
.height = dest_h
};
PXP_SetOutputBufferConfig(LV_GPU_NXP_PXP_ID, &outputBufferConfig);
lv_gpu_nxp_pxp_run();
}
#endif /*LV_USE_GPU_NXP_PXP*/