1 /*
2 * Copyright 2015 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define MODULE_TAG "mpp_allocator"
18
19 #include "mpp_mem.h"
20 #include "mpp_debug.h"
21 #include "mpp_common.h"
22 #include "mpp_allocator.h"
23 #include "mpp_allocator_impl.h"
24
25 #include "os_allocator.h"
26
27 #include <linux/drm.h>
28
29 #define MPP_ALLOCATOR_LOCK(p) pthread_mutex_lock(&(p)->lock);
30 #define MPP_ALLOCATOR_UNLOCK(p) pthread_mutex_unlock(&(p)->lock);
31
32 typedef enum OsAllocatorApiId_e {
33 ALLOC_API_ALLOC,
34 ALLOC_API_FREE,
35 ALLOC_API_IMPORT,
36 ALLOC_API_RELEASE,
37 ALLOC_API_MMAP,
38 ALLOC_API_BUTT,
39 } OsAllocatorApiId;
40
mpp_allocator_api_wrapper(MppAllocator allocator,MppBufferInfo * info,OsAllocatorApiId id)41 static MPP_RET mpp_allocator_api_wrapper(MppAllocator allocator,
42 MppBufferInfo *info,
43 OsAllocatorApiId id)
44 {
45 if (NULL == allocator || NULL == info || id >= ALLOC_API_BUTT) {
46 mpp_err_f("invalid input: allocator %p info %p id %d\n",
47 allocator, info, id);
48 return MPP_ERR_UNKNOW;
49 }
50
51 MPP_RET ret = MPP_NOK;
52 MppAllocatorImpl *p = (MppAllocatorImpl *)allocator;
53 OsAllocatorFunc func;
54
55 MPP_ALLOCATOR_LOCK(p);
56 switch (id) {
57 case ALLOC_API_ALLOC : {
58 func = p->os_api.alloc;
59 } break;
60 case ALLOC_API_FREE : {
61 func = p->os_api.free;
62 } break;
63 case ALLOC_API_IMPORT : {
64 func = p->os_api.import;
65 } break;
66 case ALLOC_API_RELEASE : {
67 func = p->os_api.release;
68 } break;
69 case ALLOC_API_MMAP : {
70 func = p->os_api.mmap;
71 } break;
72 default : {
73 func = NULL;
74 } break;
75 }
76
77 if (func && p->ctx)
78 ret = func(p->ctx, info);
79
80 MPP_ALLOCATOR_UNLOCK(p);
81
82 return ret;
83 }
84
mpp_allocator_alloc(MppAllocator allocator,MppBufferInfo * info)85 static MPP_RET mpp_allocator_alloc(MppAllocator allocator, MppBufferInfo *info)
86 {
87 return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_ALLOC);
88 }
89
mpp_allocator_free(MppAllocator allocator,MppBufferInfo * info)90 static MPP_RET mpp_allocator_free(MppAllocator allocator, MppBufferInfo *info)
91 {
92 return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_FREE);
93 }
94
mpp_allocator_import(MppAllocator allocator,MppBufferInfo * info)95 static MPP_RET mpp_allocator_import(MppAllocator allocator, MppBufferInfo *info)
96 {
97 return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_IMPORT);
98 }
99
mpp_allocator_release(MppAllocator allocator,MppBufferInfo * info)100 static MPP_RET mpp_allocator_release(MppAllocator allocator,
101 MppBufferInfo *info)
102 {
103 return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_RELEASE);
104 }
105
mpp_allocator_mmap(MppAllocator allocator,MppBufferInfo * info)106 static MPP_RET mpp_allocator_mmap(MppAllocator allocator, MppBufferInfo *info)
107 {
108 return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_MMAP);
109 }
110
111 static MppAllocatorApi mpp_allocator_api = {
112 .size = sizeof(mpp_allocator_api),
113 .version = 1,
114 .alloc = mpp_allocator_alloc,
115 .free = mpp_allocator_free,
116 .import = mpp_allocator_import,
117 .release = mpp_allocator_release,
118 .mmap = mpp_allocator_mmap,
119 };
120
mpp_allocator_get(MppAllocator * allocator,MppAllocatorApi ** api,MppBufferType type)121 MPP_RET mpp_allocator_get(MppAllocator *allocator,
122 MppAllocatorApi **api, MppBufferType type)
123 {
124 MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK);
125 RK_U32 flags = (type & MPP_BUFFER_FLAGS_MASK) >> 16;
126
127 if (NULL == allocator || NULL == api || buffer_type >= MPP_BUFFER_TYPE_BUTT) {
128 mpp_err_f("invalid input: allocator %p api %p type %d\n",
129 allocator, api, buffer_type);
130 return MPP_ERR_UNKNOW;
131 }
132
133 MppAllocatorImpl *p = mpp_malloc(MppAllocatorImpl, 1);
134 if (NULL == p) {
135 mpp_err("mpp_allocator_get failed to malloc allocator context\n");
136 return MPP_ERR_NULL_PTR;
137 } else {
138 p->type = buffer_type;
139 p->flags = flags;
140 }
141
142 MPP_RET ret = os_allocator_get(&p->os_api, buffer_type);
143
144 if (MPP_OK == ret) {
145 MppAllocatorCfg cfg = {
146 .alignment = SZ_4K,
147 .flags = flags,
148 };
149 ret = p->os_api.open(&p->ctx, &cfg);
150 }
151 if (MPP_OK == ret) {
152 pthread_mutexattr_t attr;
153 pthread_mutexattr_init(&attr);
154 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
155 pthread_mutex_init(&p->lock, &attr);
156 pthread_mutexattr_destroy(&attr);
157
158 *allocator = p;
159 *api = &mpp_allocator_api;
160 } else {
161 mpp_err("mpp_allocator_get type %d failed\n", type);
162 mpp_free(p);
163 *allocator = NULL;
164 *api = NULL;
165 }
166
167 return ret;
168 }
169
mpp_allocator_put(MppAllocator * allocator)170 MPP_RET mpp_allocator_put(MppAllocator *allocator)
171 {
172 if (NULL == allocator) {
173 mpp_err_f("invalid input: allocator %p\n", allocator);
174 return MPP_ERR_NULL_PTR;
175 }
176
177 MppAllocatorImpl *p = (MppAllocatorImpl *)*allocator;
178
179 if (!p)
180 return MPP_OK;
181 *allocator = NULL;
182
183 if (p->os_api.close && p->ctx)
184 p->os_api.close(p->ctx);
185 pthread_mutex_destroy(&p->lock);
186 mpp_free(p);
187
188 return MPP_OK;
189 }
190
get_real_allocator_type(const MppAllocator allocator)191 MppBufferType get_real_allocator_type(const MppAllocator allocator)
192 {
193 MppAllocatorImpl *p = (MppAllocatorImpl *)allocator;
194 MppBufferType type = allocator ? p->os_api.type : MPP_BUFFER_TYPE_BUTT;
195
196 return type;
197 }