• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "display_gralloc.h"
17 #include <errno.h>
18 #include <inttypes.h>
19 #include <pthread.h>
20 #include <stdio.h>
21 #include <sys/mman.h>
22 #include <sys/shm.h>
23 #include <securec.h>
24 #include "buffer_handle.h"
25 #include "display_type.h"
26 #include "disp_common.h"
27 #include "hdf_log.h"
28 #include "osal_mem.h"
29 
30 #define DEFAULT_READ_WRITE_PERMISSIONS   0666
31 #define MAX_MALLOC_SIZE                  0x10000000L
32 #define SHM_MAX_KEY                      10000
33 #define SHM_START_KEY                    1
34 #define INVALID_SHMID -1
35 #define BITS_PER_BYTE 8
36 
37 #define DIV_ROUND_UP(n, d)   (((n) + (d)-1) / (d))
38 #define ALIGN_UP(x, a)       ((((x) + ((a)-1)) / (a)) * (a))
39 #define HEIGHT_ALIGN         2U
40 #define WIDTH_ALIGN          8U
41 #define MAX_PLANES           3
42 
43 #undef  HDF_LOG_TAG
44 #define HDF_LOG_TAG          display_gralloc_c
45 
46 typedef struct {
47     BufferHandle hdl;
48     int32_t shmid;
49 } PriBufferHandle;
50 
51 typedef struct {
52     uint32_t numPlanes;
53     uint32_t radio[MAX_PLANES];
54 } PlaneLayoutInfo;
55 
56 typedef struct {
57     uint32_t format;
58     uint32_t bitsPerPixel; // bits per pixel for first plane
59     const PlaneLayoutInfo *planes;
60 } FormatInfo;
61 
62 struct GrallocManager {
63     pthread_mutex_t mutex;
64     pthread_mutexattr_t mutexattr;
65     int32_t count;
66 };
67 
68 static struct GrallocManager g_grallocManager;
69 
70 static const PlaneLayoutInfo g_yuv420SPLayout = {
71     .numPlanes = 2,
72     .radio = { 4, 2 },
73 };
74 
75 static const PlaneLayoutInfo g_yuv420PLayout = {
76     .numPlanes = 3,
77     .radio = { 4, 1, 1 },
78 };
79 
GetGrallocMgr(void)80 static void GetGrallocMgr(void)
81 {
82     g_grallocManager.count++;
83 }
84 
PutGrallocMgr(void)85 static int32_t PutGrallocMgr(void)
86 {
87     g_grallocManager.count--;
88     return g_grallocManager.count;
89 }
90 
LockGrallocMgr(void)91 static void LockGrallocMgr(void)
92 {
93     pthread_mutex_lock(&g_grallocManager.mutex);
94 }
95 
UnlockGrallocMgr(void)96 static void UnlockGrallocMgr(void)
97 {
98     pthread_mutex_unlock(&g_grallocManager.mutex);
99 }
100 
GetFormatInfo(uint32_t format)101 static const FormatInfo *GetFormatInfo(uint32_t format)
102 {
103     static const FormatInfo fmtInfos[] = {
104         {PIXEL_FMT_RGBX_8888,  32, NULL},  {PIXEL_FMT_RGBA_8888, 32,  NULL},
105         {PIXEL_FMT_BGRX_8888,  32, NULL},  {PIXEL_FMT_BGRA_8888, 32,  NULL},
106         {PIXEL_FMT_RGB_888,    24, NULL},  {PIXEL_FMT_BGR_565,   16,  NULL},
107         {PIXEL_FMT_RGBA_5551,  16, NULL},  {PIXEL_FMT_RGB_565,   16,  NULL},
108         {PIXEL_FMT_BGRX_4444,  16, NULL},  {PIXEL_FMT_BGRA_4444, 16,  NULL},
109         {PIXEL_FMT_RGBA_4444,  16, NULL},  {PIXEL_FMT_RGBX_4444, 16,  NULL},
110         {PIXEL_FMT_BGRX_5551,  16, NULL},  {PIXEL_FMT_BGRA_5551, 16,  NULL},
111         {PIXEL_FMT_YCBCR_420_SP, 8, &g_yuv420SPLayout}, {PIXEL_FMT_YCRCB_420_SP, 8, &g_yuv420SPLayout},
112         {PIXEL_FMT_YCBCR_420_P, 8, &g_yuv420PLayout}, {PIXEL_FMT_YCRCB_420_P, 8, &g_yuv420PLayout},
113     };
114 
115     for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) {
116         if (fmtInfos[i].format == format) {
117             return &fmtInfos[i];
118         }
119     }
120     HDF_LOGE("the format can not support %d %d", format, PIXEL_FMT_RGBA_8888);
121     return NULL;
122 }
123 
AdjustStrideFromFormat(uint32_t format,uint32_t width)124 static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t width)
125 {
126     const FormatInfo *fmtInfo = GetFormatInfo(format);
127     if ((fmtInfo != NULL) && (fmtInfo->planes != NULL)) {
128         uint32_t sum = fmtInfo->planes->radio[0];
129         for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) {
130             sum += fmtInfo->planes->radio[i];
131         }
132         if (sum > 0) {
133             width = DIV_ROUND_UP((width * sum), fmtInfo->planes->radio[0]);
134         }
135     }
136     return width;
137 }
138 
InitBufferHandle(PriBufferHandle * buffer,const AllocInfo * info)139 static int32_t InitBufferHandle(PriBufferHandle* buffer, const AllocInfo* info)
140 {
141     int32_t size;
142     int32_t stride;
143     int32_t h = ALIGN_UP(info->height, HEIGHT_ALIGN);
144     const FormatInfo *fmtInfo = GetFormatInfo(info->format);
145     if (fmtInfo == NULL) {
146         HDF_LOGE("can not get format information : %d", buffer->hdl.format);
147         return DISPLAY_FAILURE;
148     }
149 
150     stride = ALIGN_UP(AdjustStrideFromFormat(info->format, info->width), WIDTH_ALIGN) *
151         fmtInfo->bitsPerPixel / BITS_PER_BYTE;
152     size = h * stride;
153     buffer->hdl.width = info->width;
154     buffer->hdl.stride = stride;
155     buffer->hdl.height = info->height;
156     buffer->hdl.size = size;
157     buffer->hdl.usage = info->usage;
158     buffer->hdl.fd = -1;
159     buffer->shmid = INVALID_SHMID;
160     buffer->hdl.format = info->format;
161     buffer->hdl.reserveInts = (sizeof(PriBufferHandle) - sizeof(BufferHandle) -
162         buffer->hdl.reserveFds * sizeof(uint32_t)) / sizeof(uint32_t);
163     return DISPLAY_SUCCESS;
164 }
165 
AllocShm(BufferHandle * buffer)166 static int32_t AllocShm(BufferHandle *buffer)
167 {
168     static int32_t key = SHM_START_KEY;
169     int32_t shmid;
170 
171     while ((shmid = shmget(key, buffer->size, IPC_CREAT | IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS)) < 0) {
172         if (errno != EEXIST) {
173             HDF_LOGE("%s: fail to alloc the shared memory, errno = %d", __func__, errno);
174             return DISPLAY_FAILURE;
175         }
176         key++;
177         if (key >= SHM_MAX_KEY) {
178             key = SHM_START_KEY;
179         }
180     }
181     void *pBase = shmat(shmid, NULL, 0);
182     if (pBase == ((void *)-1)) {
183         HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno);
184         if (shmctl(shmid, IPC_RMID, 0) == -1) {
185             HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
186         }
187         return DISPLAY_FAILURE;
188     }
189     buffer->virAddr = pBase;
190     buffer->key = key;
191     ((PriBufferHandle*)buffer)->shmid = shmid;
192     key++;
193     if (memset_s(pBase, buffer->size, 0x0, buffer->size) != EOK) {
194         HDF_LOGE("memset_s failure");
195         if (shmctl(shmid, IPC_RMID, 0) == -1) {
196             HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
197         }
198         return DISPLAY_FAILURE;
199     }
200     if (key >= SHM_MAX_KEY) {
201         key = SHM_START_KEY;
202     }
203     return DISPLAY_SUCCESS;
204 }
205 
AllocMem(const AllocInfo * info,BufferHandle ** buffer)206 static int32_t AllocMem(const AllocInfo* info, BufferHandle **buffer)
207 {
208     int32_t ret;
209 
210     DISPLAY_CHK_RETURN((buffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in buffer is null", __func__));
211     DISPLAY_CHK_RETURN((info == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in info is null", __func__));
212     PriBufferHandle* priBuffer = calloc(1, sizeof(PriBufferHandle));
213     DISPLAY_CHK_RETURN((priBuffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: can not calloc errno : %d",
214         __func__, errno));
215     ret = InitBufferHandle(priBuffer, info);
216     DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, HDF_LOGE("%s: can not init buffe handle",
217         __func__); goto OUT);
218 
219     BufferHandle *bufferHdl = &priBuffer->hdl;
220     DISPLAY_CHK_RETURN(((bufferHdl->size > MAX_MALLOC_SIZE) || (bufferHdl->size == 0)),
221         DISPLAY_FAILURE, HDF_LOGE("%s: size is invalid %d ", __func__, bufferHdl->size); goto OUT);
222     LockGrallocMgr();
223     if (bufferHdl->usage == HBM_USE_MEM_SHARE) {
224         ret = AllocShm(bufferHdl);
225     } else {
226         HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, bufferHdl->usage);
227         ret = DISPLAY_NOT_SUPPORT;
228     }
229 
230 OUT:
231     if ((ret != DISPLAY_SUCCESS) && (bufferHdl != NULL)) {
232         free(bufferHdl);
233         bufferHdl = NULL;
234     }
235     *buffer = bufferHdl;
236     UnlockGrallocMgr();
237     return ret;
238 }
239 
FreeShm(BufferHandle * buffer)240 static void FreeShm(BufferHandle *buffer)
241 {
242     CHECK_NULLPOINTER_RETURN(buffer->virAddr);
243     if (shmdt(buffer->virAddr) == -1) {
244         HDF_LOGE("%s: Fail to free shared memory, errno = %d", __func__, errno);
245     }
246     if (shmctl(((PriBufferHandle*)buffer)->shmid, IPC_RMID, 0) == -1) {
247         HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
248     }
249 }
250 
FreeMem(BufferHandle * buffer)251 static void FreeMem(BufferHandle *buffer)
252 {
253     CHECK_NULLPOINTER_RETURN(buffer);
254     if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
255         HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
256         return;
257     }
258 
259     LockGrallocMgr();
260     switch (buffer->usage) {
261         case HBM_USE_MEM_SHARE:
262             FreeShm(buffer);
263             break;
264         default:
265             HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
266     }
267     UnlockGrallocMgr();
268 }
269 
MmapShm(BufferHandle * buffer)270 static void *MmapShm(BufferHandle *buffer)
271 {
272     int32_t shmid;
273 
274     shmid = shmget(buffer->key, buffer->size, IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS);
275     if (shmid < 0) {
276         HDF_LOGE("%s: Fail to mmap the shared memory, errno = %d", __func__, errno);
277         return NULL;
278     }
279     void *pBase = shmat(shmid, NULL, 0);
280     if (pBase == ((void *)-1)) {
281         HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno);
282         return NULL;
283     }
284     ((PriBufferHandle*)buffer)->shmid = shmid;
285     HDF_LOGI("%s: Mmap shared memory succeed", __func__);
286     return pBase;
287 }
288 
Mmap(BufferHandle * buffer)289 static void *Mmap(BufferHandle *buffer)
290 {
291     void *temp = NULL;
292 
293     CHECK_NULLPOINTER_RETURN_VALUE(buffer, NULL);
294     if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
295         HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
296         return NULL;
297     }
298 
299     LockGrallocMgr();
300     switch (buffer->usage) {
301         case HBM_USE_MEM_SHARE:
302             temp = MmapShm(buffer);
303             break;
304         default:
305             HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
306             break;
307     }
308     UnlockGrallocMgr();
309     return temp;
310 }
311 
UnmapShm(BufferHandle * buffer)312 static int32_t UnmapShm(BufferHandle *buffer)
313 {
314     if (shmdt(buffer->virAddr) == -1) {
315         HDF_LOGE("%s: Fail to unmap shared memory errno =  %d", __func__, errno);
316         return DISPLAY_FAILURE;
317     }
318     int32_t shmid = ((PriBufferHandle*)buffer)->shmid;
319     if ((shmid != INVALID_SHMID) && (shmctl(shmid, IPC_RMID, 0) == -1)) {
320         HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
321     }
322     return DISPLAY_SUCCESS;
323 }
324 
Unmap(BufferHandle * buffer)325 static int32_t Unmap(BufferHandle *buffer)
326 {
327     int32_t ret;
328 
329     CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR);
330     CHECK_NULLPOINTER_RETURN_VALUE(buffer->virAddr, DISPLAY_NULL_PTR);
331     if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
332         HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
333         return DISPLAY_FAILURE;
334     }
335     LockGrallocMgr();
336     switch (buffer->usage) {
337         case  HBM_USE_MEM_SHARE:
338             ret = UnmapShm(buffer);
339             break;
340         default:
341             HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
342             ret = DISPLAY_FAILURE;
343             break;
344     }
345     UnlockGrallocMgr();
346     return ret;
347 }
348 
GrallocInitialize(GrallocFuncs ** funcs)349 int32_t GrallocInitialize(GrallocFuncs **funcs)
350 {
351     static GrallocFuncs *gFuncs = NULL;
352 
353     if (funcs == NULL) {
354         HDF_LOGE("%s: funcs is null", __func__);
355         return DISPLAY_NULL_PTR;
356     }
357     if (gFuncs == NULL) {
358         gFuncs = (GrallocFuncs *)OsalMemCalloc(sizeof(GrallocFuncs));
359         if (gFuncs == NULL) {
360             HDF_LOGE("%s: gFuncs is null", __func__);
361             return DISPLAY_NULL_PTR;
362         }
363         pthread_mutexattr_init(&g_grallocManager.mutexattr);
364         pthread_mutexattr_setpshared(&g_grallocManager.mutexattr, PTHREAD_PROCESS_SHARED);
365         pthread_mutex_init(&g_grallocManager.mutex, &g_grallocManager.mutexattr);
366         gFuncs->AllocMem = AllocMem;
367         gFuncs->FreeMem = FreeMem;
368         gFuncs->Mmap = Mmap;
369         gFuncs->Unmap = Unmap;
370     }
371     *funcs = gFuncs;
372     GetGrallocMgr();
373     HDF_LOGI("%s: gralloc initialize success", __func__);
374     return DISPLAY_SUCCESS;
375 }
376 
GrallocUninitialize(GrallocFuncs * funcs)377 int32_t GrallocUninitialize(GrallocFuncs *funcs)
378 {
379     if (funcs == NULL) {
380         HDF_LOGE("%s: funcs is null", __func__);
381         return DISPLAY_NULL_PTR;
382     }
383     if (PutGrallocMgr() == 0) {
384         pthread_mutexattr_destroy(&g_grallocManager.mutexattr);
385         pthread_mutex_destroy(&g_grallocManager.mutex);
386         OsalMemFree(funcs);
387     }
388     HDF_LOGI("%s: gralloc uninitialize success", __func__);
389     return DISPLAY_SUCCESS;
390 }
391