• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Rockchip Electronics 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 #ifndef __MPP_BUFFER_H__
17 #define __MPP_BUFFER_H__
18 
19 #include "rk_type.h"
20 #include "mpp_err.h"
21 
22 /*
23  * MppBuffer module has several functions:
24  *
25  * 1. buffer get / put / reference management / external commit / get info.
26  *    this part is the basic user interface for MppBuffer.
27  *
28  *    function:
29  *
30  *    mpp_buffer_get
31  *    mpp_buffer_put
32  *    mpp_buffer_inc_ref
33  *    mpp_buffer_commit
34  *    mpp_buffer_info_get
35  *
36  * 2. user buffer working flow control abstraction.
37  *    buffer should attach to certain group, and buffer mode control the buffer usage flow.
38  *    this part is also a part of user interface.
39  *
40  *    function:
41  *
42  *    mpp_buffer_group_get
43  *    mpp_buffer_group_normal_get
44  *    mpp_buffer_group_limit_get
45  *    mpp_buffer_group_put
46  *    mpp_buffer_group_limit_config
47  *
48  * 3. buffer allocator management
49  *    this part is for allocator on different os, it does not have user interface
50  *    it will support normal buffer, ion buffer, Linux v4l2 vb2 buffer
51  *    user can only use MppBufferType to choose.
52  *
53  */
54 
55 /*
56  * mpp buffer group support two work flow mode:
57  *
58  * normal flow: all buffer are generated by MPP
59  *              under this mode, buffer pool is maintained internally
60  *
61  *              typical call flow:
62  *
63  *              mpp_buffer_group_get()          return A
64  *              mpp_buffer_get(A)               return a    ref +1 -> used
65  *              mpp_buffer_inc_ref(a)                       ref +1
66  *              mpp_buffer_put(a)                           ref -1
67  *              mpp_buffer_put(a)                           ref -1 -> unused
68  *              mpp_buffer_group_put(A)
69  *
70  * commit flow: all buffer are commited out of MPP
71  *              under this mode, buffers is commit by external api.
72  *              normally MPP only use it but not generate it.
73  *
74  *              typical call flow:
75  *
76  *              ==== external allocator ====
77  *              mpp_buffer_group_get()          return A
78  *              mpp_buffer_commit(A, x)
79  *              mpp_buffer_commit(A, y)
80  *
81  *              ======= internal user ======
82  *              mpp_buffer_get(A)               return a
83  *              mpp_buffer_get(A)               return b
84  *              mpp_buffer_put(a)
85  *              mpp_buffer_put(b)
86  *
87  *              ==== external allocator ====
88  *              mpp_buffer_group_put(A)
89  *
90  *              NOTE: commit interface required group handle to record group information
91  */
92 
93 /*
94  * mpp buffer group has two buffer limit mode: normal and limit
95  *
96  * normal mode: allows any buffer size and always general new buffer is no unused buffer
97  *              is available.
98  *              This mode normally use with normal flow and is used for table / stream buffer
99  *
100  * limit mode : restrict the buffer's size and count in the buffer group. if try to calloc
101  *              buffer with different size or extra count it will fail.
102  *              This mode normally use with commit flow and is used for frame buffer
103  */
104 
105 /*
106  * NOTE: normal mode is recommanded to work with normal flow, working with limit  mode is not.
107  *       limit  mode is recommanded to work with commit flow, working with normal mode is not.
108  */
109 typedef enum {
110     MPP_BUFFER_INTERNAL,
111     MPP_BUFFER_EXTERNAL,
112     MPP_BUFFER_MODE_BUTT,
113 } MppBufferMode;
114 
115 /*
116  * the mpp buffer has serval types:
117  *
118  * normal   : normal malloc buffer for unit test or hardware simulation
119  * ion      : use ion device under Linux, MppBuffer will encapsulte ion file handle
120  * ext_dma  : the DMABUF(DMA buffers) come from the application
121  * drm      : use the drm device interface for memory management
122  */
123 typedef enum {
124     MPP_BUFFER_TYPE_NORMAL,
125     MPP_BUFFER_TYPE_ION,
126     MPP_BUFFER_TYPE_EXT_DMA,
127     MPP_BUFFER_TYPE_DRM,
128     MPP_BUFFER_TYPE_BUTT,
129 } MppBufferType;
130 
131 #define MPP_BUFFER_TYPE_MASK            0x0000FFFF
132 
133 /*
134  * MPP_BUFFER_FLAGS cooperate with MppBufferType
135  * 16 high bits of MppBufferType are used in flags
136  *
137  * eg:
138  * DRM CMA buffer : MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_CONTIG
139  *                  = 0x00010003
140  * DRM SECURE buffer: MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_SECURE
141  *                  = 0x00080003
142  *
143  * flags originate from drm_rockchip_gem_mem_type
144  */
145 
146 #define MPP_BUFFER_FLAGS_MASK           0x000f0000      // ROCKCHIP_BO_MASK << 16
147 #define MPP_BUFFER_FLAGS_CONTIG         0x00010000      // ROCKCHIP_BO_CONTIG << 16
148 #define MPP_BUFFER_FLAGS_CACHABLE       0x00020000      // ROCKCHIP_BO_CACHABLE << 16
149 #define MPP_BUFFER_FLAGS_WC             0x00040000      // ROCKCHIP_BO_WC << 16
150 #define MPP_BUFFER_FLAGS_SECURE         0x00080000      // ROCKCHIP_BO_SECURE << 16
151 
152 /*
153  * MppBufferInfo variable's meaning is different in different MppBufferType
154  *
155  * Common
156  * index - the buffer index used to track buffer in buffer pool
157  * size  - the buffer size
158  *
159  * MPP_BUFFER_TYPE_NORMAL
160  *
161  * ptr  - virtual address of normal malloced buffer
162  * fd   - unused and set to -1, the allocator would return its
163  *         internal buffer counter number
164  *
165  * MPP_BUFFER_TYPE_ION
166  *
167  * ptr  - virtual address of ion buffer in user space
168  * hnd  - ion handle in user space
169  * fd   - ion buffer file handle for map / unmap
170  *
171  */
172 typedef struct MppBufferInfo_t {
173     MppBufferType   type;
174     size_t          size;
175     void            *ptr;
176     void            *hnd;
177     int             fd;
178     int             index;
179 } MppBufferInfo;
180 
181 #define BUFFER_GROUP_SIZE_DEFAULT           (SZ_1M*80)
182 
183 /*
184  * mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer)
185  *
186  * 1. group - specified the MppBuffer to be attached to.
187  *    group can be NULL then this buffer will attached to default legecy group
188  *    Default to NULL on mpp_buffer_import case
189  *
190  * 2. info  - input information for the output MppBuffer
191  *    info can NOT be NULL. It must contain at least one of ptr/fd.
192  *
193  * 3. buffer - generated MppBuffer from MppBufferInfo.
194  *    buffer can be NULL then the buffer is commit to group with unused status.
195  *    Otherwise generated buffer will be directly got and ref_count increased.
196  *    Default to NULL on mpp_buffer_commit case
197  *
198  * mpp_buffer_commit usage:
199  *
200  * Add a external buffer info to group. This buffer will be on unused status.
201  * Typical usage is on MediaPlayer gralloc Graphic buffer then commit these buffer
202  * to decoder's buffer group. Then decoder will recycle these buffer and return buffer reference
203  * to MediaPlayer for display.
204  *
205  * mpp_buffer_import usage:
206  *
207  * Transfer a external buffer info to MppBuffer but it is not expected to attached to certain
208  * buffer group. So the group is set to NULL. Then this buffer can be used for MppFrame/MppPacket.
209  * Typical usage is for image processing. Image processing normally will be a oneshot operation
210  * It does not need complicated group management. But in other hand mpp still need to know the
211  * imported buffer is leak or not and trace its usage inside mpp process. So we attach this kind
212  * of buffer to default misc buffer group for management.
213  */
214 #define mpp_buffer_commit(group, info) \
215         mpp_buffer_import_with_tag(group, info, NULL, MODULE_TAG, __FUNCTION__)
216 
217 #define mpp_buffer_import(buffer, info) \
218         mpp_buffer_import_with_tag(NULL, info, buffer, MODULE_TAG, __FUNCTION__)
219 
220 #define mpp_buffer_get(group, buffer, size) \
221         mpp_buffer_get_with_tag(group, buffer, size, MODULE_TAG, __FUNCTION__)
222 
223 #define mpp_buffer_put(buffer) \
224         mpp_buffer_put_with_caller(buffer, __FUNCTION__)
225 
226 #define mpp_buffer_inc_ref(buffer) \
227         mpp_buffer_inc_ref_with_caller(buffer, __FUNCTION__)
228 
229 #define mpp_buffer_info_get(buffer, info) \
230         mpp_buffer_info_get_with_caller(buffer, info, __FUNCTION__)
231 
232 #define mpp_buffer_read(buffer, offset, data, size) \
233         mpp_buffer_read_with_caller(buffer, offset, data, size, __FUNCTION__)
234 
235 #define mpp_buffer_write(buffer, offset, data, size) \
236         mpp_buffer_write_with_caller(buffer, offset, data, size, __FUNCTION__)
237 
238 #define mpp_buffer_get_ptr(buffer) \
239         mpp_buffer_get_ptr_with_caller(buffer, __FUNCTION__)
240 
241 #define mpp_buffer_get_fd(buffer) \
242         mpp_buffer_get_fd_with_caller(buffer, __FUNCTION__)
243 
244 #define mpp_buffer_get_size(buffer) \
245         mpp_buffer_get_size_with_caller(buffer, __FUNCTION__)
246 
247 #define mpp_buffer_get_index(buffer) \
248         mpp_buffer_get_index_with_caller(buffer, __FUNCTION__)
249 
250 #define mpp_buffer_set_index(buffer, index) \
251         mpp_buffer_set_index_with_caller(buffer, index, __FUNCTION__)
252 
253 #define mpp_buffer_get_offset(buffer) \
254         mpp_buffer_get_offset_with_caller(buffer, __FUNCTION__)
255 
256 #define mpp_buffer_set_offset(buffer, offset) \
257         mpp_buffer_set_offset_with_caller(buffer, offset, __FUNCTION__)
258 
259 #define mpp_buffer_group_get_internal(group, type, ...) \
260         mpp_buffer_group_get(group, type, MPP_BUFFER_INTERNAL, MODULE_TAG, __FUNCTION__)
261 
262 #define mpp_buffer_group_get_external(group, type, ...) \
263         mpp_buffer_group_get(group, type, MPP_BUFFER_EXTERNAL, MODULE_TAG, __FUNCTION__)
264 
265 #ifdef __cplusplus
266 extern "C" {
267 #endif
268 
269 /*
270  * MppBuffer interface
271  * these interface will change value of group and buffer so before calling functions
272  * parameter need to be checked.
273  *
274  * IMPORTANT:
275  * mpp_buffer_import_with_tag - compounded interface for commit and import
276  *
277  */
278 MPP_RET mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer,
279                                    const char *tag, const char *caller);
280 MPP_RET mpp_buffer_get_with_tag(MppBufferGroup group, MppBuffer *buffer, size_t size,
281                                 const char *tag, const char *caller);
282 MPP_RET mpp_buffer_put_with_caller(MppBuffer buffer, const char *caller);
283 MPP_RET mpp_buffer_inc_ref_with_caller(MppBuffer buffer, const char *caller);
284 
285 MPP_RET mpp_buffer_info_get_with_caller(MppBuffer buffer, MppBufferInfo *info, const char *caller);
286 MPP_RET mpp_buffer_read_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller);
287 MPP_RET mpp_buffer_write_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller);
288 void   *mpp_buffer_get_ptr_with_caller(MppBuffer buffer, const char *caller);
289 int     mpp_buffer_get_fd_with_caller(MppBuffer buffer, const char *caller);
290 size_t  mpp_buffer_get_size_with_caller(MppBuffer buffer, const char *caller);
291 int     mpp_buffer_get_index_with_caller(MppBuffer buffer, const char *caller);
292 MPP_RET mpp_buffer_set_index_with_caller(MppBuffer buffer, int index, const char *caller);
293 size_t  mpp_buffer_get_offset_with_caller(MppBuffer buffer, const char *caller);
294 MPP_RET mpp_buffer_set_offset_with_caller(MppBuffer buffer, size_t offset, const char *caller);
295 
296 MPP_RET mpp_buffer_group_get(MppBufferGroup *group, MppBufferType type, MppBufferMode mode,
297                              const char *tag, const char *caller);
298 MPP_RET mpp_buffer_group_put(MppBufferGroup group);
299 MPP_RET mpp_buffer_group_clear(MppBufferGroup group);
300 RK_S32  mpp_buffer_group_unused(MppBufferGroup group);
301 size_t  mpp_buffer_group_usage(MppBufferGroup group);
302 MppBufferMode mpp_buffer_group_mode(MppBufferGroup group);
303 MppBufferType mpp_buffer_group_type(MppBufferGroup group);
304 
305 /*
306  * size  : 0 - no limit, other - max buffer size
307  * count : 0 - no limit, other - max buffer count
308  */
309 MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count);
310 
311 RK_U32 mpp_buffer_total_now(void);
312 RK_U32 mpp_buffer_total_max(void);
313 
314 #ifdef __cplusplus
315 }
316 #endif
317 
318 #endif /* __MPP_BUFFER_H__ */