Files
base/middleware/gpu_hal/src/hal_gpu.c
2025-11-07 09:57:14 +08:00

343 lines
14 KiB
C

/*
* hal_gpu.c
*@brief hal gpu function file.
*
* Copyright (c) 2012 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
* 2022/06/01 create this file
*/
#include <dispss/disp.h>
#include <dispss/disp_data_type.h>
#include <g2dlite/g2dlite.h>
#include "hal_gpu.h"
#include "hal_g2dlite.h"
#include "hal_asw.h"
#include "hal_comm_inner.h"
#include <asw/asw.h>
#define GPU_MAX_ANGLE 180 /* 180 ~360 filp */
#define GPU_ROTATE_MAX_ANGLE 5 /* 10: 0~20 */
#define GPU_ROTATE_IMG_CNT (GPU_MAX_ANGLE / (GPU_ROTATE_MAX_ANGLE * 2))
static COMM_RotateContext g_gpuContext = {0};
/* The first rotation or rotation of the picture sends a change */
static bool g_ratateChanged = true;
/* rotate buf */
static COMM_RotateBuf g_rotateBuf[GPU_ROTATE_IMG_CNT + 1] = { NULL, NULL }; /* add tmp buf */
extern struct g2dlite_device g2dlite_dev;
static void GPU_DeleteRotateBuf(uint32_t rotateImgCnt)
{
for (int i = 0; i < rotateImgCnt; i++) {
if (g_rotateBuf[i].buf != NULL) {
free((void *)g_rotateBuf[i].buf);
g_rotateBuf[i].bufLen = 0;
g_rotateBuf[i].buf = NULL;
}
}
/* free tmp buf */
if (g_rotateBuf[GPU_ROTATE_IMG_CNT].buf != NULL) {
free((void *)g_rotateBuf[GPU_ROTATE_IMG_CNT].buf);
g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen = 0;
g_rotateBuf[GPU_ROTATE_IMG_CNT].buf = NULL;
}
}
static int GPU_MallocRotateBuf(const HAL_RotateInfo *info, uint32_t rotateImgCnt, uint32_t sideLen, uint32_t rotateSrcStride, uint32_t rotateDstStride)
{
/* malloc tmp buf */
if ((g_rotateBuf[GPU_ROTATE_IMG_CNT].buf == NULL) || (sideLen * rotateDstStride > g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen)) {
if (g_rotateBuf[GPU_ROTATE_IMG_CNT].buf != NULL) {
free((void *)g_rotateBuf[GPU_ROTATE_IMG_CNT].buf);
}
g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen = sideLen * rotateDstStride;
g_rotateBuf[GPU_ROTATE_IMG_CNT].buf = (uint8_t*)pvPortMallocAligned(g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen, 0x1000);
if (g_rotateBuf[GPU_ROTATE_IMG_CNT].buf == NULL) {
HAL_LOG_E(HAL_MOD_GPU, "pvPortMallocAligned rotate buf, len:%d error!\n",g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen);
g_rotateBuf[GPU_ROTATE_IMG_CNT].bufLen = 0;
g_rotateBuf[GPU_ROTATE_IMG_CNT].buf = NULL;
GPU_DeleteRotateBuf(rotateImgCnt);
return HAL_GPU_NO_MEM;
}
}
/* Save the image rotated degrees */
for (int i = 0; i < rotateImgCnt; i++) {
uint32_t stride = rotateDstStride;
if (i == 0) {
stride = rotateSrcStride;
}
/* Reapply for buf when the buf is too small or the picture is sent differently */
if ((g_rotateBuf[i].buf == NULL) || (sideLen * stride > g_rotateBuf[i].bufLen)) {
if (g_rotateBuf[i].buf != NULL) {
free((void *)g_rotateBuf[i].buf);
}
g_rotateBuf[i].bufLen = sideLen * stride;
g_rotateBuf[i].buf = (uint8_t*)pvPortMallocAligned(g_rotateBuf[i].bufLen, 0x1000);
if (g_rotateBuf[i].buf == NULL) {
HAL_LOG_E(HAL_MOD_GPU, "pvPortMallocAligned rotate buf, len:%d error!\n",g_rotateBuf[i].bufLen);
g_rotateBuf[i].bufLen = 0;
g_rotateBuf[i].buf = NULL;
GPU_DeleteRotateBuf(rotateImgCnt);
return HAL_GPU_NO_MEM;
}
g_ratateChanged = true;
}
}
return HAL_SUCCESS;
}
static int GPU_SaveRotateImg(const HAL_RotateInfo *info, uint32_t maxRotateAngle, uint32_t sideLen, uint32_t rotateSrcStride, uint32_t rotateDstStride)
{
/* need to re-save the rotated image */
if (!g_ratateChanged && (info->srcBuf == g_gpuContext.rotateInfo.srcBuf) && (info->srcRect.x == g_gpuContext.rotateInfo.srcRect.x) && (info->srcRect.y == g_gpuContext.rotateInfo.srcRect.y) &&
(info->srcRect.w == g_gpuContext.rotateInfo.srcRect.w) && (info->srcRect.h == g_gpuContext.rotateInfo.srcRect.h) &&
(info->srcFmt == g_gpuContext.rotateInfo.srcFmt) && (info->dstFmt == g_gpuContext.rotateInfo.dstFmt) && (info->bgColor == g_gpuContext.rotateInfo.bgColor)) {
HAL_LOG_I(HAL_MOD_GPU, "the rotate img is not change!");
return HAL_SUCCESS;
}
uint32_t rotateImgCnt = GPU_MAX_ANGLE / (maxRotateAngle * 2);
/* clean buf, save the image rotated degrees */
HAL_FillRectInfo rectInfo = {0};
rectInfo.buf = g_rotateBuf[0].buf;
rectInfo.color = 0;
rectInfo.fmt = info->srcFmt;
rectInfo.stride = rotateSrcStride;
rectInfo.dstRect.x = 0;
rectInfo.dstRect.y = 0;
rectInfo.dstRect.w = sideLen;
rectInfo.dstRect.h = sideLen;
for (int i = 0; i < rotateImgCnt; i++) {
if (i != 0) {
rectInfo.fmt = info->dstFmt;
rectInfo.stride = rotateDstStride;
}
rectInfo.buf = g_rotateBuf[i].buf;
int ret = HAL_ASW_FillRect(&rectInfo);
CHECK_RETURN(HAL_MOD_GPU, ret, "HAL_ASW_FillRect");
}
rectInfo.fmt = info->dstFmt;
rectInfo.stride = rotateDstStride;
rectInfo.buf = g_rotateBuf[GPU_ROTATE_IMG_CNT].buf;
int ret = HAL_ASW_FillRect(&rectInfo);
CHECK_RETURN(HAL_MOD_GPU, ret, "HAL_ASW_FillRect");
int copy_x = (sideLen - info->srcRect.w) / 2;
int copy_y = (sideLen - info->srcRect.h) / 2;
HAL_G2DLITE_FastCopyInfo src, dst;
src.buf = info->srcBuf;
src.rect.x = info->srcRect.x;
src.rect.y = info->srcRect.y;
src.rect.w = info->srcRect.w;
src.rect.h = info->srcRect.h;
src.fmt = info->srcFmt;
src.stride = info->srcStride;
dst.buf = g_rotateBuf[0].buf;
dst.rect.x = copy_x;
dst.rect.y = copy_y;
dst.rect.w = info->srcRect.w;
dst.rect.h = info->srcRect.h;
dst.fmt = info->srcFmt;
dst.stride = rotateSrcStride;
ret = HAL_G2DLITE_FastCopy(&src, &dst);
CHECK_RETURN(HAL_MOD_GPU, ret, "HAL_G2DLITE_FastCopy");
ASW_RotateInfo rotateInfo = {0};
rotateInfo.rotate.srcRect.x = 0;
rotateInfo.rotate.srcRect.y = 0;
rotateInfo.rotate.srcRect.w = sideLen;
rotateInfo.rotate.srcRect.h = sideLen;
rotateInfo.rotate.srcFmt = info->srcFmt;
rotateInfo.rotate.srcStride = rotateSrcStride;
rotateInfo.rotate.srcBuf = g_rotateBuf[0].buf;
rotateInfo.rotate.dstWidth = sideLen;
rotateInfo.rotate.dstHeight = sideLen;
rotateInfo.rotate.dstFmt = info->dstFmt;
rotateInfo.rotate.bgColor = info->bgColor;
rotateInfo.tmpBuf = g_rotateBuf[GPU_ROTATE_IMG_CNT].buf;
rotateInfo.tmpStride = rotateDstStride;
/* save the image rotated maxRotateAngle degrees */
rotateInfo.rotate.dstStride = rotateDstStride;
for (int i = 1; i < rotateImgCnt; i++) {
rotateInfo.rotate.angle = (maxRotateAngle * 2) * i;
rotateInfo.rotate.dstBuf = g_rotateBuf[i].buf;
int ret = ASW_Rotate(&rotateInfo);
CHECK_RETURN(HAL_MOD_GPU, ret, "ASW_Rotate");
}
g_gpuContext.rotateInfo = *info;
g_ratateChanged = false;
return HAL_SUCCESS;
}
static int GPU_Rotate(const HAL_RotateInfo *info, uint32_t maxRotateAngle)
{
int ret = HAL_SUCCESS;
HAL_LOG_D(HAL_MOD_GPU, "src:rect[%u, %u, %u, %u] buf[%#x] stride[%u] format[%d]",
info->srcRect.x, info->srcRect.y, info->srcRect.w, info->srcRect.h,
info->srcBuf, info->srcStride, info->srcFmt);
HAL_LOG_D(HAL_MOD_GPU, "dst:width[%u] height[%u] buf[%#x] stride[%u] format[%d] angle[%lf] bgColor[%#x]",
info->dstWidth, info->dstHeight, info->dstBuf, info->dstStride, info->dstFmt, info->angle, info->bgColor);
if ((maxRotateAngle < GPU_ROTATE_MAX_ANGLE) || (GPU_MAX_ANGLE % maxRotateAngle != 0)) {
HAL_LOG_E(HAL_MOD_GPU, "maxRotateAngle[%d] Must be greater than %u and It has to be divisible by 180!\n",maxRotateAngle, GPU_ROTATE_MAX_ANGLE);
return HAL_GPU_ERR_PARAM;
}
int srcBpp = COMM_getFmtBpp(info->srcFmt);
if (srcBpp < 0){
return HAL_GPU_ERR_PARAM;
}
int dstBpp = COMM_getFmtBpp(info->dstFmt);
if (dstBpp < 0){
return HAL_GPU_ERR_PARAM;
}
uint32_t rotateImgCnt = GPU_MAX_ANGLE / (maxRotateAngle * 2);
/* Apply buf with the diagonal of the picture as the side length */
uint32_t rotateWidth = (uint32_t)sqrt(info->srcRect.w * info->srcRect.w + info->srcRect.h * info->srcRect.h) + 1;
/* align 8 */
rotateWidth = rotateWidth % 8 ? ((rotateWidth / 8 + 1) * 8) : rotateWidth;
/* The target area should not be smaller than the diagonal of the picture */
if (rotateWidth > info->dstWidth || rotateWidth > info->dstHeight) {
HAL_LOG_E(HAL_MOD_GPU, "dst: width[%u] and height[%u] Must be greater than %u!\n",info->dstWidth, info->dstHeight, rotateWidth);
return HAL_GPU_ERR_PARAM;
}
uint32_t rotateSrcStride = rotateWidth * srcBpp;
uint32_t rotateDstStride = rotateWidth * dstBpp;
HAL_LOG_I(HAL_MOD_GPU, "rotate:width[%u] height[%u] srcBpp[%d] dstBpp[%d]", rotateWidth, rotateWidth, srcBpp, dstBpp);
/* Save the image rotated degrees */
ret = GPU_MallocRotateBuf(info, rotateImgCnt, rotateWidth, rotateSrcStride, rotateDstStride);
CHECK_RETURN(HAL_MOD_GPU, ret, "GPU_MallocRotateBuf");
if (!g_ratateChanged && g_gpuContext.maxRotateAngle != maxRotateAngle) {
g_ratateChanged = true;
g_gpuContext.maxRotateAngle = maxRotateAngle;
}
/* clean buf, save the image rotated degrees */
ret = GPU_SaveRotateImg(info, maxRotateAngle, rotateWidth, rotateSrcStride, rotateDstStride);
CHECK_GOTO(HAL_MOD_GPU, ret, "GPU_SaveRotateImg", GOTO);
int posX = 0;
int posY = 0;
if ((rotateWidth != info->dstWidth) || (rotateWidth != info->dstHeight)) {
posX = (info->dstWidth - rotateWidth) / 2;
posY = (info->dstHeight - rotateWidth) / 2;
}
HAL_LOG_I(HAL_MOD_GPU, "out rotate rect:posX[%d] posY[%d]", posX, posY);
ASW_RotateInfo rotateInfo = {0};
rotateInfo.rotate.srcRect.x = 0;
rotateInfo.rotate.srcRect.y = 0;
rotateInfo.rotate.srcRect.w = rotateWidth;
rotateInfo.rotate.srcRect.h = rotateWidth;
rotateInfo.rotate.srcFmt = info->srcFmt;
rotateInfo.rotate.srcStride = rotateSrcStride;
rotateInfo.rotate.dstWidth = rotateWidth;
rotateInfo.rotate.dstHeight = rotateWidth;
rotateInfo.rotate.dstFmt = info->dstFmt;
rotateInfo.rotate.dstBuf = (info->dstBuf + posY * info->dstStride + posX * dstBpp);
rotateInfo.rotate.dstStride = info->dstStride;
rotateInfo.rotate.bgColor = info->bgColor;
rotateInfo.tmpBuf = g_rotateBuf[GPU_ROTATE_IMG_CNT].buf;
rotateInfo.tmpStride = rotateDstStride;
rotateInfo.rotate.angle = info->angle;
while (rotateInfo.rotate.angle < 0) {
rotateInfo.rotate.angle += 360;
}
while (rotateInfo.rotate.angle > 360) {
rotateInfo.rotate.angle -= 360;
}
if ((rotateInfo.rotate.angle <= maxRotateAngle || rotateInfo.rotate.angle >= 360 - maxRotateAngle) ||
((GPU_MAX_ANGLE - maxRotateAngle <= rotateInfo.rotate.angle) && (rotateInfo.rotate.angle <= GPU_MAX_ANGLE + maxRotateAngle))) {
rotateInfo.rotate.srcBuf = g_rotateBuf[0].buf;
ret = ASW_Rotate(&rotateInfo);
CHECK_GOTO(HAL_MOD_GPU, ret, "ASW_Rotate", GOTO);
return HAL_SUCCESS;
}
for (int i = 1; i < rotateImgCnt; i++) {
if ((maxRotateAngle + (maxRotateAngle * 2 * (i - 1)) <= rotateInfo.rotate.angle) &&
(rotateInfo.rotate.angle <= maxRotateAngle + (maxRotateAngle * 2 * i)) ||
((rotateInfo.rotate.angle >= GPU_MAX_ANGLE + (maxRotateAngle + maxRotateAngle * 2 * (i - 1))) &&
(rotateInfo.rotate.angle <= GPU_MAX_ANGLE + (maxRotateAngle + maxRotateAngle * 2 * i)))) {
rotateInfo.rotate.srcStride = rotateDstStride;
rotateInfo.rotate.srcFmt = info->dstFmt;
rotateInfo.rotate.srcBuf = g_rotateBuf[i].buf;
rotateInfo.rotate.angle -= (maxRotateAngle * 2 * i);
ret = ASW_Rotate(&rotateInfo);
CHECK_GOTO(HAL_MOD_GPU, ret, "ASW_Rotate", GOTO);
break;
}
}
return HAL_SUCCESS;
GOTO:
GPU_DeleteRotateBuf(rotateImgCnt);
return ret;
}
int HAL_GPU_Rotate(const HAL_RotateInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->dstBuf, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->srcBuf, HAL_GPU_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstWidth, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstHeight, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
if ((info->dstStride == 0) || (info->dstStride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_ASW, "dst stride[%d] is invalid,It has to be a multiple of 8!\n", info->dstStride);
return HAL_GPU_ERR_PARAM;
}
#endif
return GPU_Rotate(info, GPU_MAX_ANGLE / 2);
}
int HAL_GPU_RotateEx(const HAL_RotateInfo *info)
{
#if HAL_DEBUG_MODE
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->dstBuf, HAL_GPU_NULL_PTR);
CHECK_NULLPTR_RETURN(HAL_MOD_GPU, info->srcBuf, HAL_GPU_NULL_PTR);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.w, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->srcRect.h, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstWidth, 1, HAL_GUI_MAX_WIDTH, HAL_GPU_ERR_PARAM);
CHECK_VALUE_RETURN(HAL_MOD_G2DLITE, info->dstHeight, 1, HAL_GUI_MAX_HEIGHT, HAL_GPU_ERR_PARAM);
if ((info->dstStride == 0) || (info->dstStride % 8 != 0)) {
HAL_LOG_E(HAL_MOD_GPU, "dst stride[%d] is invalid,It has to be a multiple of 8!\n", info->dstStride);
return HAL_GPU_ERR_PARAM;
}
#endif
return GPU_Rotate(info, GPU_ROTATE_MAX_ANGLE);
}