Home | History | Annotate | Download | only in xcore
      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