• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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