/* * 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 #include #include #include "hal_gpu.h" #include "hal_g2dlite.h" #include "hal_asw.h" #include "hal_comm_inner.h" #include #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); }