mirror of
https://github.com/openharmony/drivers_peripheral.git
synced 2026-08-24 07:45:51 -04:00
dbf0e6a3ea
Signed-off-by: frank_bing <libing3@huawei.com> Change-Id: I8225c3a461d9c57e9efe831f0e129755483a78c8
382 lines
12 KiB
C
382 lines
12 KiB
C
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "display_gralloc.h"
|
|
#include <cerrno>
|
|
#include <inttypes.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/shm.h>
|
|
#include <securec.h>
|
|
#include "buffer_handle.h"
|
|
#include "display_type.h"
|
|
#include "disp_common.h"
|
|
#include "hdf_log.h"
|
|
#include "osal_mem.h"
|
|
|
|
#define DEFAULT_READ_WRITE_PERMISSIONS 0666
|
|
#define MAX_MALLOC_SIZE 0x10000000L
|
|
#define SHM_MAX_KEY 10000
|
|
#define SHM_START_KEY 1
|
|
#define INVALID_SHMID -1
|
|
#define BITS_PER_BYTE 8
|
|
|
|
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
|
#define ALIGN_UP(x, a) ((((x) + ((a) - 1)) / (a)) * (a))
|
|
#define HEIGHT_ALIGN 2U
|
|
#define WIDTH_ALIGN 8U
|
|
#define MAX_PLANES 3
|
|
|
|
#undef HDF_LOG_TAG
|
|
#define HDF_LOG_TAG display_gralloc_c
|
|
|
|
typedef struct {
|
|
BufferHandle hdl;
|
|
int32_t shmid;
|
|
} PriBufferHandle;
|
|
|
|
typedef struct {
|
|
uint32_t numPlanes;
|
|
uint32_t radio[MAX_PLANES];
|
|
} PlaneLayoutInfo;
|
|
|
|
typedef struct {
|
|
uint32_t format;
|
|
uint32_t bitsPerPixel; // bits per pixel for first plane
|
|
const PlaneLayoutInfo *planes;
|
|
} FormatInfo;
|
|
|
|
struct GrallocManager {
|
|
pthread_mutex_t mutex;
|
|
pthread_mutexattr_t mutexattr;
|
|
int32_t count;
|
|
};
|
|
|
|
static struct GrallocManager g_grallocManager;
|
|
|
|
static const PlaneLayoutInfo g_yuv420SPLayout = {
|
|
.numPlanes = 2,
|
|
.radio = { 4, 2 },
|
|
};
|
|
|
|
static const PlaneLayoutInfo g_yuv420PLayout = {
|
|
.numPlanes = 3,
|
|
.radio = { 4, 1, 1 },
|
|
};
|
|
|
|
static void GetGrallocMgr(void)
|
|
{
|
|
g_grallocManager.count++;
|
|
}
|
|
|
|
static int32_t PutGrallocMgr(void)
|
|
{
|
|
g_grallocManager.count--;
|
|
return g_grallocManager.count;
|
|
}
|
|
|
|
static void LockGrallocMgr(void)
|
|
{
|
|
pthread_mutex_lock(&g_grallocManager.mutex);
|
|
}
|
|
|
|
static void UnlockGrallocMgr(void)
|
|
{
|
|
pthread_mutex_unlock(&g_grallocManager.mutex);
|
|
}
|
|
|
|
static const FormatInfo *GetFormatInfo(uint32_t format)
|
|
{
|
|
static const FormatInfo fmtInfos[] = {
|
|
{PIXEL_FMT_RGBX_8888, 32, NULL}, {PIXEL_FMT_RGBA_8888, 32, NULL},
|
|
{PIXEL_FMT_BGRX_8888, 32, NULL}, {PIXEL_FMT_BGRA_8888, 32, NULL},
|
|
{PIXEL_FMT_RGB_888, 24, NULL}, {PIXEL_FMT_BGR_565, 16, NULL},
|
|
{PIXEL_FMT_RGBA_5551, 16, NULL}, {PIXEL_FMT_RGB_565, 16, NULL},
|
|
{PIXEL_FMT_BGRX_4444, 16, NULL}, {PIXEL_FMT_BGRA_4444, 16, NULL},
|
|
{PIXEL_FMT_RGBA_4444, 16, NULL}, {PIXEL_FMT_RGBX_4444, 16, NULL},
|
|
{PIXEL_FMT_BGRX_5551, 16, NULL}, {PIXEL_FMT_BGRA_5551, 16, NULL},
|
|
{PIXEL_FMT_YCBCR_420_SP, 8, &g_yuv420SPLayout}, {PIXEL_FMT_YCRCB_420_SP, 8, &g_yuv420SPLayout},
|
|
{PIXEL_FMT_YCBCR_420_P, 8, &g_yuv420PLayout}, {PIXEL_FMT_YCRCB_420_P, 8, &g_yuv420PLayout},
|
|
};
|
|
|
|
for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) {
|
|
if (fmtInfos[i].format == format) {
|
|
return &fmtInfos[i];
|
|
}
|
|
}
|
|
HDF_LOGE("the format can not support %d %d", format, PIXEL_FMT_RGBA_8888);
|
|
return NULL;
|
|
}
|
|
|
|
static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t width)
|
|
{
|
|
const FormatInfo *fmtInfo = GetFormatInfo(format);
|
|
if ((fmtInfo != NULL) && (fmtInfo->planes != NULL)) {
|
|
uint32_t sum = fmtInfo->planes->radio[0];
|
|
for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) {
|
|
sum += fmtInfo->planes->radio[i];
|
|
}
|
|
if (sum > 0) {
|
|
width = DIV_ROUND_UP((width * sum), fmtInfo->planes->radio[0]);
|
|
}
|
|
}
|
|
return width;
|
|
}
|
|
|
|
static int32_t InitBufferHandle(PriBufferHandle* buffer, const AllocInfo* info)
|
|
{
|
|
int32_t size;
|
|
int32_t stride;
|
|
int32_t h = ALIGN_UP(info->height, HEIGHT_ALIGN);
|
|
const FormatInfo *fmtInfo = GetFormatInfo(info->format);
|
|
if (fmtInfo == NULL) {
|
|
HDF_LOGE("can not get format information : %d", buffer->hdl.format);
|
|
return DISPLAY_FAILURE;
|
|
}
|
|
|
|
stride = ALIGN_UP(AdjustStrideFromFormat(info->format, info->width), WIDTH_ALIGN) *
|
|
fmtInfo->bitsPerPixel / BITS_PER_BYTE;
|
|
size = h * stride;
|
|
buffer->hdl.width = info->width;
|
|
buffer->hdl.stride = stride;
|
|
buffer->hdl.height = info->height;
|
|
buffer->hdl.size = size;
|
|
buffer->hdl.usage = info->usage;
|
|
buffer->hdl.fd = -1;
|
|
buffer->shmid = INVALID_SHMID;
|
|
buffer->hdl.format = info->format;
|
|
buffer->hdl.reserveInts = (sizeof(PriBufferHandle) - sizeof(BufferHandle) -
|
|
buffer->hdl.reserveFds * sizeof(uint32_t)) / sizeof(uint32_t);
|
|
return DISPLAY_SUCCESS;
|
|
}
|
|
|
|
static int32_t AllocShm(BufferHandle *buffer)
|
|
{
|
|
static int32_t key = SHM_START_KEY;
|
|
int32_t shmid;
|
|
|
|
while ((shmid = shmget(key, buffer->size, IPC_CREAT | IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS)) < 0) {
|
|
if (errno != EEXIST) {
|
|
HDF_LOGE("%s: fail to alloc the shared memory, errno = %d", __func__, errno);
|
|
return DISPLAY_FAILURE;
|
|
}
|
|
key++;
|
|
if (key >= SHM_MAX_KEY) {
|
|
key = SHM_START_KEY;
|
|
}
|
|
}
|
|
void *pBase = shmat(shmid, NULL, 0);
|
|
if (pBase == ((void *)-1)) {
|
|
HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno);
|
|
if (shmctl(shmid, IPC_RMID, 0) == -1) {
|
|
HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
|
|
}
|
|
return DISPLAY_FAILURE;
|
|
}
|
|
buffer->virAddr = pBase;
|
|
buffer->fd = key;
|
|
((PriBufferHandle*)buffer)->shmid = shmid;
|
|
key++;
|
|
if (memset_s(pBase, buffer->size, 0x0, buffer->size) != EOK) {
|
|
HDF_LOGE("memset_s failure");
|
|
if (shmctl(shmid, IPC_RMID, 0) == -1) {
|
|
HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
|
|
}
|
|
return DISPLAY_FAILURE;
|
|
}
|
|
if (key >= SHM_MAX_KEY) {
|
|
key = SHM_START_KEY;
|
|
}
|
|
return DISPLAY_SUCCESS;
|
|
}
|
|
|
|
static int32_t AllocMem(const AllocInfo* info, BufferHandle **buffer)
|
|
{
|
|
int32_t ret;
|
|
DISPLAY_CHK_RETURN((buffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in buffer is null", __func__));
|
|
DISPLAY_CHK_RETURN((info == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in info is null", __func__));
|
|
PriBufferHandle* priBuffer = (PriBufferHandle*)calloc(1, sizeof(PriBufferHandle));
|
|
DISPLAY_CHK_RETURN((priBuffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: can not calloc errno : %d",
|
|
__func__, errno));
|
|
ret = InitBufferHandle(priBuffer, info);
|
|
DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, HDF_LOGE("%s: can not init buffe handle",
|
|
__func__); goto OUT);
|
|
|
|
BufferHandle *bufferHdl = &priBuffer->hdl;
|
|
DISPLAY_CHK_RETURN(((bufferHdl->size > MAX_MALLOC_SIZE) || (bufferHdl->size == 0)),
|
|
DISPLAY_FAILURE, HDF_LOGE("%s: size is invalid %d ", __func__, bufferHdl->size); goto OUT);
|
|
LockGrallocMgr();
|
|
if (bufferHdl->usage == HBM_USE_MEM_SHARE) {
|
|
ret = AllocShm(bufferHdl);
|
|
} else {
|
|
HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, bufferHdl->usage);
|
|
ret = DISPLAY_NOT_SUPPORT;
|
|
}
|
|
|
|
OUT:
|
|
if ((ret != DISPLAY_SUCCESS) && (bufferHdl != NULL)) {
|
|
free(bufferHdl);
|
|
bufferHdl = NULL;
|
|
}
|
|
*buffer = bufferHdl;
|
|
UnlockGrallocMgr();
|
|
return ret;
|
|
}
|
|
|
|
static void FreeShm(BufferHandle *buffer)
|
|
{
|
|
CHECK_NULLPOINTER_RETURN(buffer->virAddr);
|
|
if (shmdt(buffer->virAddr) == -1) {
|
|
HDF_LOGE("%s: Fail to free shared memory, errno = %d", __func__, errno);
|
|
}
|
|
if (shmctl(((PriBufferHandle*)buffer)->shmid, IPC_RMID, 0) == -1) {
|
|
HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
|
|
}
|
|
}
|
|
|
|
static void FreeMem(BufferHandle *buffer)
|
|
{
|
|
CHECK_NULLPOINTER_RETURN(buffer);
|
|
if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
|
|
HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
|
|
return;
|
|
}
|
|
|
|
LockGrallocMgr();
|
|
if (buffer->usage == HBM_USE_MEM_SHARE) {
|
|
FreeShm(buffer);
|
|
} else {
|
|
HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
|
|
}
|
|
UnlockGrallocMgr();
|
|
}
|
|
|
|
static void *MmapShm(BufferHandle *buffer)
|
|
{
|
|
int32_t shmid;
|
|
|
|
shmid = shmget(buffer->fd, buffer->size, IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS);
|
|
if (shmid < 0) {
|
|
HDF_LOGE("%s: Fail to mmap the shared memory, errno = %d", __func__, errno);
|
|
return NULL;
|
|
}
|
|
void *pBase = shmat(shmid, NULL, 0);
|
|
if (pBase == ((void *)-1)) {
|
|
HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno);
|
|
return NULL;
|
|
}
|
|
((PriBufferHandle*)buffer)->shmid = shmid;
|
|
HDF_LOGI("%s: Mmap shared memory succeed", __func__);
|
|
return pBase;
|
|
}
|
|
|
|
static void *Mmap(BufferHandle *buffer)
|
|
{
|
|
void *temp = NULL;
|
|
|
|
CHECK_NULLPOINTER_RETURN_VALUE(buffer, NULL);
|
|
if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
|
|
HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
|
|
return NULL;
|
|
}
|
|
|
|
LockGrallocMgr();
|
|
if (buffer->usage == HBM_USE_MEM_SHARE) {
|
|
temp = MmapShm(buffer);
|
|
} else {
|
|
HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
|
|
}
|
|
UnlockGrallocMgr();
|
|
return temp;
|
|
}
|
|
|
|
static int32_t UnmapShm(BufferHandle *buffer)
|
|
{
|
|
if (shmdt(buffer->virAddr) == -1) {
|
|
HDF_LOGE("%s: Fail to unmap shared memory errno = %d", __func__, errno);
|
|
return DISPLAY_FAILURE;
|
|
}
|
|
int32_t shmid = ((PriBufferHandle*)buffer)->shmid;
|
|
if ((shmid != INVALID_SHMID) && (shmctl(shmid, IPC_RMID, 0) == -1)) {
|
|
HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
|
|
}
|
|
return DISPLAY_SUCCESS;
|
|
}
|
|
|
|
static int32_t Unmap(BufferHandle *buffer)
|
|
{
|
|
int32_t ret;
|
|
|
|
CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR);
|
|
CHECK_NULLPOINTER_RETURN_VALUE(buffer->virAddr, DISPLAY_NULL_PTR);
|
|
if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
|
|
HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
|
|
return DISPLAY_FAILURE;
|
|
}
|
|
LockGrallocMgr();
|
|
if (buffer->usage == HBM_USE_MEM_SHARE) {
|
|
ret = UnmapShm(buffer);
|
|
} else {
|
|
HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
|
|
ret = DISPLAY_FAILURE;
|
|
}
|
|
UnlockGrallocMgr();
|
|
return ret;
|
|
}
|
|
|
|
int32_t GrallocInitialize(GrallocFuncs **funcs)
|
|
{
|
|
static GrallocFuncs *gFuncs = NULL;
|
|
|
|
if (funcs == NULL) {
|
|
HDF_LOGE("%s: funcs is null", __func__);
|
|
return DISPLAY_NULL_PTR;
|
|
}
|
|
if (gFuncs == NULL) {
|
|
gFuncs = (GrallocFuncs *)OsalMemCalloc(sizeof(GrallocFuncs));
|
|
if (gFuncs == NULL) {
|
|
HDF_LOGE("%s: gFuncs is null", __func__);
|
|
return DISPLAY_NULL_PTR;
|
|
}
|
|
pthread_mutexattr_init(&g_grallocManager.mutexattr);
|
|
pthread_mutexattr_setpshared(&g_grallocManager.mutexattr, PTHREAD_PROCESS_SHARED);
|
|
pthread_mutex_init(&g_grallocManager.mutex, &g_grallocManager.mutexattr);
|
|
gFuncs->AllocMem = AllocMem;
|
|
gFuncs->FreeMem = FreeMem;
|
|
gFuncs->Mmap = Mmap;
|
|
gFuncs->Unmap = Unmap;
|
|
}
|
|
*funcs = gFuncs;
|
|
GetGrallocMgr();
|
|
HDF_LOGI("%s: gralloc initialize success", __func__);
|
|
return DISPLAY_SUCCESS;
|
|
}
|
|
|
|
int32_t GrallocUninitialize(GrallocFuncs *funcs)
|
|
{
|
|
if (funcs == NULL) {
|
|
HDF_LOGE("%s: funcs is null", __func__);
|
|
return DISPLAY_NULL_PTR;
|
|
}
|
|
if (PutGrallocMgr() == 0) {
|
|
pthread_mutexattr_destroy(&g_grallocManager.mutexattr);
|
|
pthread_mutex_destroy(&g_grallocManager.mutex);
|
|
OsalMemFree(funcs);
|
|
}
|
|
HDF_LOGI("%s: gralloc uninitialize success", __func__);
|
|
return DISPLAY_SUCCESS;
|
|
}
|