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 (at) 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 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 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 * 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 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 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 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 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 * 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> 143 DrmBoBuffer::find_3a_stats () 144 { 145 return find_typed_attach<X3aStats> (); 146 } 147 148 SmartPtr<SwappedBuffer> 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 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 175 DrmBoBufferPool::~DrmBoBufferPool () 176 { 177 _display.release (); 178 XCAM_LOG_DEBUG ("DrmBoBufferPool destructed"); 179 } 180 181 bool 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 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 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> 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> 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