1 /*
2 * drm_bo_buffer.cpp - drm bo buffer
3 *
4 * Copyright (c) 2015 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #include "drm_bo_buffer.h"
22 #include "x3a_stats_pool.h"
23
24 #define OCL_TILING_NONE 0
25
26 namespace XCam {
27
DrmBoData(SmartPtr<DrmDisplay> & display,drm_intel_bo * bo)28 DrmBoData::DrmBoData (SmartPtr<DrmDisplay> &display, drm_intel_bo *bo)
29 : _display (display)
30 , _bo (bo)
31 , _buf (NULL)
32 , _prime_fd (-1)
33 , _need_close_fd (true)
34 {
35 XCAM_ASSERT (display.ptr ());
36 XCAM_ASSERT (bo);
37 }
38
~DrmBoData()39 DrmBoData::~DrmBoData ()
40 {
41 unmap ();
42 if (_bo)
43 drm_intel_bo_unreference (_bo);
44 if (_prime_fd != -1 && _need_close_fd)
45 close (_prime_fd);
46 }
47
48 uint8_t *
map()49 DrmBoData::map ()
50 {
51 if (_buf) {
52 return _buf;
53 }
54
55 uint32_t tiling_mode, swizzle_mode;
56
57 drm_intel_bo_get_tiling (_bo, &tiling_mode, &swizzle_mode);
58
59 if (tiling_mode != OCL_TILING_NONE) {
60 if (drm_intel_gem_bo_map_gtt (_bo) != 0)
61 return NULL;
62 }
63 else {
64 if (drm_intel_bo_map (_bo, 1) != 0)
65 return NULL;
66 }
67
68 _buf = (uint8_t *)_bo->virt;
69 return _buf;
70 }
71
72 bool
unmap()73 DrmBoData::unmap ()
74 {
75 if (!_buf || !_bo)
76 return true;
77
78 uint32_t tiling_mode, swizzle_mode;
79
80 drm_intel_bo_get_tiling (_bo, &tiling_mode, &swizzle_mode);
81
82 if (tiling_mode != OCL_TILING_NONE) {
83 if (drm_intel_gem_bo_unmap_gtt (_bo) != 0)
84 return false;
85 }
86 else {
87 if (drm_intel_bo_unmap (_bo) != 0)
88 return false;
89 }
90
91 _buf = NULL;
92 return true;
93 }
94
95 int
get_fd()96 DrmBoData::get_fd ()
97 {
98 if (_prime_fd == -1) {
99 if (drm_intel_bo_gem_export_to_prime (_bo, &_prime_fd) < 0) {
100 _prime_fd = -1;
101 XCAM_LOG_ERROR ("DrmBoData: failed to obtain prime fd: %s", strerror(errno));
102 }
103 _need_close_fd = true;
104 }
105
106 return _prime_fd;
107 }
108
109 bool
set_prime_fd(int fd,bool need_close)110 DrmBoData::set_prime_fd (int fd, bool need_close)
111 {
112 if (_prime_fd != -1) {
113 XCAM_LOG_ERROR ("DrmBoData: set_dma_fd failed, the current prime fd was already set");
114 return false;
115 }
116 _prime_fd = fd;
117 _need_close_fd = need_close;
118 return true;
119 }
120
DrmBoBuffer(const VideoBufferInfo & info,const SmartPtr<DrmBoData> & data)121 DrmBoBuffer::DrmBoBuffer (const VideoBufferInfo &info, const SmartPtr<DrmBoData> &data)
122 : BufferProxy (info, data)
123 , SwappedBuffer (info, data)
124 {
125 XCAM_ASSERT (data.ptr ());
126 }
127
128 drm_intel_bo *
get_bo()129 DrmBoBuffer::get_bo ()
130 {
131 SmartPtr<BufferData> data = get_buffer_data ();
132 SmartPtr<DrmBoData> bo = data.dynamic_cast_ptr<DrmBoData> ();
133
134 XCAM_FAIL_RETURN(
135 WARNING,
136 bo.ptr(),
137 NULL,
138 "DrmBoBuffer get_buffer_data failed with NULL");
139 return bo->get_bo ();
140 }
141
142 SmartPtr<X3aStats>
find_3a_stats()143 DrmBoBuffer::find_3a_stats ()
144 {
145 return find_typed_attach<X3aStats> ();
146 }
147
148 SmartPtr<SwappedBuffer>
create_new_swap_buffer(const VideoBufferInfo & info,SmartPtr<BufferData> & data)149 DrmBoBuffer::create_new_swap_buffer (
150 const VideoBufferInfo &info, SmartPtr<BufferData> &data)
151 {
152 XCAM_ASSERT (get_buffer_data ().ptr () == data.ptr ());
153
154 SmartPtr<DrmBoData> bo = data.dynamic_cast_ptr<DrmBoData> ();
155
156 XCAM_FAIL_RETURN(
157 WARNING,
158 bo.ptr(),
159 NULL,
160 "DrmBoBuffer create_new_swap_buffer failed with NULL buffer data");
161
162 return new DrmBoBuffer (info, bo);
163 }
164
DrmBoBufferPool(SmartPtr<DrmDisplay> & display)165 DrmBoBufferPool::DrmBoBufferPool (SmartPtr<DrmDisplay> &display)
166 : _swap_flags (SwappedBuffer::SwapNone)
167 , _swap_init_order ((uint32_t)(SwappedBuffer::OrderY0Y1) | (uint32_t)(SwappedBuffer::OrderUV0UV1))
168 , _display (display)
169 {
170 xcam_mem_clear (_swap_offsets);
171 XCAM_ASSERT (display.ptr ());
172 XCAM_LOG_DEBUG ("DrmBoBufferPool constructed");
173 }
174
~DrmBoBufferPool()175 DrmBoBufferPool::~DrmBoBufferPool ()
176 {
177 _display.release ();
178 XCAM_LOG_DEBUG ("DrmBoBufferPool destructed");
179 }
180
181 bool
update_swap_init_order(uint32_t init_order)182 DrmBoBufferPool::update_swap_init_order (uint32_t init_order)
183 {
184 VideoBufferInfo info = get_video_info ();
185 XCAM_ASSERT (info.format);
186
187 if ((_swap_flags & (uint32_t)(SwappedBuffer::SwapY)) && !(init_order & (uint32_t)(SwappedBuffer::OrderYMask))) {
188 XCAM_LOG_WARNING ("update swap init order failed, need init Y order, error order:0x%04x", init_order);
189 return false;
190 }
191
192 if ((_swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) && !(init_order & (uint32_t)(SwappedBuffer::OrderUVMask))) {
193 XCAM_LOG_WARNING ("update swap init order failed, need init UV order, error order:0x%04x", init_order);
194 return false;
195 }
196 _swap_init_order = init_order;
197
198 XCAM_FAIL_RETURN (
199 WARNING,
200 init_swap_order (info),
201 false,
202 "CL3aImageProcessor post_config failed");
203
204 update_video_info_unsafe (info);
205
206 return true;
207 }
208
209 bool
fixate_video_info(VideoBufferInfo & info)210 DrmBoBufferPool::fixate_video_info (VideoBufferInfo &info)
211 {
212 if (info.format != V4L2_PIX_FMT_NV12)
213 return true;
214
215 VideoBufferInfo out_info;
216 out_info.init (info.format, info.width, info.height, info.aligned_width, info.aligned_height);
217
218 if (_swap_flags & (uint32_t)(SwappedBuffer::SwapY)) {
219 _swap_offsets[SwappedBuffer::SwapYOffset0] = out_info.offsets[0];
220 _swap_offsets[SwappedBuffer::SwapYOffset1] = out_info.size;
221 out_info.size += out_info.strides[0] * out_info.aligned_height;
222 }
223
224 if (_swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) {
225 _swap_offsets[SwappedBuffer::SwapUVOffset0] = out_info.offsets[1];
226 _swap_offsets[SwappedBuffer::SwapUVOffset1] = out_info.size;
227 out_info.size += out_info.strides[1] * (out_info.aligned_height + 1) / 2;
228 }
229
230 if(!init_swap_order (out_info)) {
231 XCAM_LOG_ERROR ("DrmBoBufferPool: fix video info faield to init swap order");
232 return false;
233 }
234
235 info = out_info;
236 return true;
237 }
238
239 bool
init_swap_order(VideoBufferInfo & info)240 DrmBoBufferPool::init_swap_order (VideoBufferInfo &info)
241 {
242 if (_swap_flags & (uint32_t)(SwappedBuffer::SwapY)) {
243 if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderYMask)) == (uint32_t)(SwappedBuffer::OrderY0Y1)) {
244 info.offsets[0] = _swap_offsets[SwappedBuffer::SwapYOffset0];
245 } else if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderYMask)) ==
246 (uint32_t)(SwappedBuffer::OrderY1Y0)) {
247 info.offsets[0] = _swap_offsets[SwappedBuffer::SwapYOffset1];
248 } else {
249 XCAM_LOG_WARNING ("BufferPool: There's unknown init_swap_order(Y):0x%04x", _swap_init_order);
250 return false;
251 }
252 }
253
254 if (_swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) {
255 if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderUVMask)) == (uint32_t)(SwappedBuffer::OrderUV0UV1)) {
256 info.offsets[1] = _swap_offsets[SwappedBuffer::SwapUVOffset0];
257 } else if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderUVMask)) ==
258 (uint32_t)(SwappedBuffer::OrderUV1UV0)) {
259 info.offsets[1] = _swap_offsets[SwappedBuffer::SwapUVOffset1];
260 } else {
261 XCAM_LOG_WARNING ("BufferPool: There's unknown init_swap_order(UV):0x%04x", _swap_init_order);
262 return false;
263 }
264 }
265
266 return true;
267 }
268
269 SmartPtr<BufferData>
allocate_data(const VideoBufferInfo & buffer_info)270 DrmBoBufferPool::allocate_data (const VideoBufferInfo &buffer_info)
271 {
272 SmartPtr<DrmBoData> bo = _display->create_drm_bo (_display, buffer_info);
273 return bo;
274 }
275
276 SmartPtr<BufferProxy>
create_buffer_from_data(SmartPtr<BufferData> & data)277 DrmBoBufferPool::create_buffer_from_data (SmartPtr<BufferData> &data)
278 {
279 const VideoBufferInfo & info = get_video_info ();
280 SmartPtr<DrmBoData> bo_data = data.dynamic_cast_ptr<DrmBoData> ();
281 XCAM_ASSERT (bo_data.ptr ());
282
283 SmartPtr<DrmBoBuffer> out_buf = new DrmBoBuffer (info, bo_data);
284 XCAM_ASSERT (out_buf.ptr ());
285 out_buf->set_swap_info (_swap_flags, _swap_offsets);
286 return out_buf;
287 }
288
289 };
290