• 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 <stdio.h>
20 #include <sys/mman.h>
21 #include <sys/shm.h>
22 #include <securec.h>
23 #include "buffer_handle.h"
24 #include "display_type.h"
25 #include "disp_common.h"
26 #include "hdf_log.h"
27 
28 #define DEFAULT_READ_WRITE_PERMISSIONS   0666
29 #define MAX_MALLOC_SIZE                  0x10000000L
30 #define SHM_MAX_KEY                      10000
31 #define SHM_START_KEY                    1
32 #define INVALID_SHMID -1
33 #define BITS_PER_BYTE 8
34 
35 #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
36 #define ALIGN_UP(x, a) ((((x) + ((a)-1)) / (a)) * (a))
37 #define HEIGHT_ALIGN 2U
38 #define WIDTH_ALIGN 8U
39 #define MAX_PLANES 3
40 
41 typedef struct {
42     BufferHandle hdl;
43     int32_t shmid;
44 } PriBufferHandle;
45 
46 typedef struct {
47     uint32_t numPlanes;
48     uint32_t radio[MAX_PLANES];
49 } PlaneLayoutInfo;
50 
51 typedef struct {
52     uint32_t format;
53     uint32_t bitsPerPixel; // bits per pixel for first plane
54     const PlaneLayoutInfo *planes;
55 } FormatInfo;
56 
57 static const PlaneLayoutInfo g_yuv420SPLayout = {
58     .numPlanes = 2,
59     .radio = { 4, 2 },
60 };
61 
62 static const PlaneLayoutInfo g_yuv420PLayout = {
63     .numPlanes = 3,
64     .radio = { 4, 1, 1 },
65 };
66 
GetFormatInfo(uint32_t format)67 static const FormatInfo *GetFormatInfo(uint32_t format)
68 {
69     static const FormatInfo fmtInfos[] = {
70         {PIXEL_FMT_RGBX_8888,  32, NULL},  {PIXEL_FMT_RGBA_8888, 32,  NULL},
71         {PIXEL_FMT_BGRX_8888,  32, NULL},  {PIXEL_FMT_BGRA_8888, 32,  NULL},
72         {PIXEL_FMT_RGB_888,    24, NULL},  {PIXEL_FMT_BGR_565,   16,  NULL},
73         {PIXEL_FMT_RGBA_5551,  16, NULL},  {PIXEL_FMT_RGB_565,   16,  NULL},
74         {PIXEL_FMT_BGRX_4444,  16, NULL},  {PIXEL_FMT_BGRA_4444, 16,  NULL},
75         {PIXEL_FMT_RGBA_4444,  16, NULL},  {PIXEL_FMT_RGBX_4444, 16,  NULL},
76         {PIXEL_FMT_BGRX_5551,  16, NULL},  {PIXEL_FMT_BGRA_5551, 16,  NULL},
77         {PIXEL_FMT_YCBCR_420_SP, 8, &g_yuv420SPLayout}, {PIXEL_FMT_YCRCB_420_SP, 8, &g_yuv420SPLayout},
78         {PIXEL_FMT_YCBCR_420_P, 8, &g_yuv420PLayout}, {PIXEL_FMT_YCRCB_420_P, 8, &g_yuv420PLayout},
79     };
80 
81     for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) {
82         if (fmtInfos[i].format == format) {
83             return &fmtInfos[i];
84         }
85     }
86     HDF_LOGE("the format can not support %d %d", format, PIXEL_FMT_RGBA_8888);
87     return NULL;
88 }
89 
AdjustStrideFromFormat(uint32_t format,uint32_t width)90 static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t width)
91 {
92     const FormatInfo *fmtInfo = GetFormatInfo(format);
93     if ((fmtInfo != NULL) && (fmtInfo->planes != NULL)) {
94         uint32_t sum = fmtInfo->planes->radio[0];
95         for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) {
96             sum += fmtInfo->planes->radio[i];
97         }
98         if (sum > 0) {
99             width = DIV_ROUND_UP((width * sum), fmtInfo->planes->radio[0]);
100         }
101     }
102     return width;
103 }
104 
InitBufferHandle(PriBufferHandle * buffer,const AllocInfo * info)105 static int32_t InitBufferHandle(PriBufferHandle* buffer, const AllocInfo* info)
106 {
107     int32_t size;
108     int32_t stride;
109     int32_t h = ALIGN_UP(info->height, HEIGHT_ALIGN);
110     const FormatInfo *fmtInfo = GetFormatInfo(info->format);
111     if (fmtInfo == NULL) {
112         HDF_LOGE("can not get format information : %d", buffer->hdl.format);
113         return DISPLAY_FAILURE;
114     }
115 
116     stride = ALIGN_UP(AdjustStrideFromFormat(info->format, info->width), WIDTH_ALIGN) *
117         fmtInfo->bitsPerPixel / BITS_PER_BYTE;
118     size = h * stride;
119     buffer->hdl.width = info->width;
120     buffer->hdl.stride = stride;
121     buffer->hdl.height = info->height;
122     buffer->hdl.size = size;
123     buffer->hdl.usage = info->usage;
124     buffer->hdl.fd = -1;
125     buffer->shmid = INVALID_SHMID;
126     buffer->hdl.format = info->format;
127     buffer->hdl.reserveInts = (sizeof(PriBufferHandle) - sizeof(BufferHandle) -
128         buffer->hdl.reserveFds * sizeof(uint32_t)) / sizeof(uint32_t);
129     return DISPLAY_SUCCESS;
130 }
131 
AllocShm(BufferHandle * buffer)132 static int32_t AllocShm(BufferHandle *buffer)
133 {
134     static int32_t key = SHM_START_KEY;
135     int32_t shmid;
136 
137     while ((shmid = shmget(key, buffer->size, IPC_CREAT | IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS)) < 0) {
138         if (errno != EEXIST) {
139             HDF_LOGE("%s: fail to alloc the shared memory, errno = %d", __func__, errno);
140             return DISPLAY_FAILURE;
141         }
142         key++;
143         if (key >= SHM_MAX_KEY) {
144             key = SHM_START_KEY;
145         }
146     }
147     void *pBase = shmat(shmid, NULL, 0);
148     if (pBase == ((void *)-1)) {
149         HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno);
150         if (shmctl(shmid, IPC_RMID, 0) == -1) {
151             HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
152         }
153         return DISPLAY_FAILURE;
154     }
155     buffer->virAddr = pBase;
156     buffer->key = key;
157     ((PriBufferHandle*)buffer)->shmid = shmid;
158     key++;
159     if (key >= SHM_MAX_KEY) {
160         key = SHM_START_KEY;
161     }
162     return DISPLAY_SUCCESS;
163 }
164 
AllocMem(const AllocInfo * info,BufferHandle ** buffer)165 static int32_t AllocMem(const AllocInfo* info, BufferHandle **buffer)
166 {
167     int32_t ret;
168     BufferHandle *bufferHdl = NULL;
169     DISPLAY_CHK_RETURN((buffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in buffer is null", __func__));
170     DISPLAY_CHK_RETURN((info == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: in info is null", __func__));
171     PriBufferHandle* priBuffer = calloc(1, sizeof(PriBufferHandle));
172     DISPLAY_CHK_RETURN((priBuffer == NULL), DISPLAY_NULL_PTR, HDF_LOGE("%s: can not calloc errno : %d",
173         __func__, errno));
174     ret = InitBufferHandle(priBuffer, info);
175     DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, HDF_LOGE("%s: can not init buffe handle",
176         __func__); goto OUT);
177 
178     bufferHdl = &priBuffer->hdl;
179     DISPLAY_CHK_RETURN(((bufferHdl->size > MAX_MALLOC_SIZE) || (bufferHdl->size == 0)),
180         DISPLAY_FAILURE, HDF_LOGE("%s: size is invalid %d ", __func__, bufferHdl->size); goto out);
181 
182     if (bufferHdl->usage == HBM_USE_MEM_SHARE) {
183         ret = AllocShm(bufferHdl);
184     } else {
185         HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, bufferHdl->usage);
186         ret = DISPLAY_NOT_SUPPORT;
187     }
188 
189 OUT:
190     if ((ret != DISPLAY_SUCCESS) && (bufferHdl != NULL)) {
191         free(bufferHdl);
192         bufferHdl = NULL;
193     }
194     *buffer = bufferHdl;
195     return ret;
196 }
197 
FreeShm(BufferHandle * buffer)198 static void FreeShm(BufferHandle *buffer)
199 {
200     CHECK_NULLPOINTER_RETURN(buffer->virAddr);
201     if (shmdt(buffer->virAddr) == -1) {
202         HDF_LOGE("%s: Fail to free shared memory, errno = %d", __func__, errno);
203     }
204     if (shmctl(((PriBufferHandle*)buffer)->shmid, IPC_RMID, 0) == -1) {
205         HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
206     }
207 }
208 
FreeMem(BufferHandle * buffer)209 static void FreeMem(BufferHandle *buffer)
210 {
211     CHECK_NULLPOINTER_RETURN(buffer);
212     if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
213         HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
214         return;
215     }
216 
217     if (buffer->usage == HBM_USE_MEM_SHARE) {
218         FreeShm(buffer);
219         return;
220     } else {
221         HDF_LOGE("%s: not support memory usage: 0x%" PRIx64 "", __func__, buffer->usage);
222     }
223 }
224 
Mmap(BufferHandle * buffer)225 static void *Mmap(BufferHandle *buffer)
226 {
227     CHECK_NULLPOINTER_RETURN_VALUE(buffer, NULL);
228     if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
229         HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
230         return NULL;
231     }
232 
233     int32_t shmid = shmget(buffer->key, buffer->size, IPC_EXCL | DEFAULT_READ_WRITE_PERMISSIONS);
234     if (shmid < 0) {
235         HDF_LOGE("%s: Fail to mmap the shared memory, errno = %d", __func__, errno);
236         return NULL;
237     }
238     void *pBase = shmat(shmid, NULL, 0);
239     if (pBase == ((void *)-1)) {
240         HDF_LOGE("%s: Fail to attach the shared memory, errno = %d", __func__, errno);
241         return NULL;
242     }
243     ((PriBufferHandle*)buffer)->shmid = shmid;
244     HDF_LOGI("%s: Mmap shared memory succeed", __func__);
245     return pBase;
246 }
247 
Unmap(BufferHandle * buffer)248 static int32_t Unmap(BufferHandle *buffer)
249 {
250     CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR);
251     CHECK_NULLPOINTER_RETURN_VALUE(buffer->virAddr, DISPLAY_NULL_PTR);
252     if ((buffer->size > MAX_MALLOC_SIZE) || (buffer->size == 0)) {
253         HDF_LOGE("%s: size is invalid, buffer->size = %d", __func__, buffer->size);
254         return DISPLAY_FAILURE;
255     }
256 
257     if (shmdt(buffer->virAddr) == -1) {
258         HDF_LOGE("%s: Fail to unmap shared memory errno =  %d", __func__, errno);
259         return DISPLAY_FAILURE;
260     }
261     int32_t shmid = ((PriBufferHandle*)buffer)->shmid;
262     if ((shmid != INVALID_SHMID) && (shmctl(shmid, IPC_RMID, 0) == -1)) {
263         HDF_LOGE("%s: Fail to free shmid, errno = %d", __func__, errno);
264     }
265     return DISPLAY_SUCCESS;
266 }
267 
GrallocInitialize(GrallocFuncs ** funcs)268 int32_t GrallocInitialize(GrallocFuncs **funcs)
269 {
270     if (funcs == NULL) {
271         HDF_LOGE("%s: funcs is null", __func__);
272         return DISPLAY_NULL_PTR;
273     }
274     GrallocFuncs *gFuncs = (GrallocFuncs *)malloc(sizeof(GrallocFuncs));
275     if (gFuncs == NULL) {
276         HDF_LOGE("%s: gFuncs is null", __func__);
277         return DISPLAY_NULL_PTR;
278     }
279     (void)memset_s(gFuncs, sizeof(GrallocFuncs), 0, sizeof(GrallocFuncs));
280     gFuncs->AllocMem = AllocMem;
281     gFuncs->FreeMem = FreeMem;
282     gFuncs->Mmap = Mmap;
283     gFuncs->Unmap = Unmap;
284     *funcs = gFuncs;
285     HDF_LOGI("%s: gralloc initialize success", __func__);
286     return DISPLAY_SUCCESS;
287 }
288 
GrallocUninitialize(GrallocFuncs * funcs)289 int32_t GrallocUninitialize(GrallocFuncs *funcs)
290 {
291     if (funcs == NULL) {
292         HDF_LOGE("%s: funcs is null", __func__);
293         return DISPLAY_NULL_PTR;
294     }
295     free(funcs);
296     HDF_LOGI("%s: gralloc uninitialize success", __func__);
297     return DISPLAY_SUCCESS;
298 }
299