/* * drm_buffer.cpp - DRM Buffer Implementation * * Copyright (c) 2021 Rockchip Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "drm_buffer.h" #include #include #include #include #include #include "dma_buffer.h" #include "drm_device.h" #include "xcam_defs.h" #include "xcam_log.h" namespace XCam { DrmBuffer::~DrmBuffer() { for (auto it = dma_bufs_.begin(); it != dma_bufs_.end();) { dma_bufs_.erase(it); } auto dev = drm_device_.lock(); if (dev != nullptr) { dev->DestroyDumbObject(dumb_object_); } } DrmBuffer::DrmBuffer(const std::shared_ptr& dev, std::unique_ptr dumb_object) : drm_device_(std::weak_ptr(dev)) { dumb_object_ = std::move(dumb_object); for (int i = 0; i < dumb_object_->num_planes; i++) { dma_bufs_.push_back(std::unique_ptr( new DmaBuffer(dumb_object_->fds[i], dumb_object_->sizes[i]))); } } int DrmBuffer::numPlanes() { return dma_bufs_.size(); } uint8_t* DrmBuffer::map(unsigned int plane) { if (plane >= dma_bufs_.size()) { return nullptr; } auto&& buf = dma_bufs_.at(plane); if (!buf->mapped()) { auto dev = drm_device_.lock(); dev->RequestMapDumbObject(dumb_object_, plane); } auto ptr = reinterpret_cast(buf->map()); buf->beginCpuAccess(DmaBufferDirection::kBidirectional); return ptr; } uint8_t* DrmBuffer::map() { return map(0); } bool DrmBuffer::unmap(unsigned int plane) { if (plane >= dma_bufs_.size()) { return false; } auto&& buf = dma_bufs_.at(plane); buf->endCpuAccess(DmaBufferDirection::kBidirectional); buf->unmap(); return true; } bool DrmBuffer::unmap() { return unmap(0); } int DrmBuffer::getFd(unsigned int plane) { if (plane >= dma_bufs_.size()) { return -1; } return dma_bufs_.at(plane)->getFd(); } size_t DrmBuffer::getSize() { return getSize(0); } size_t DrmBuffer::getSize(unsigned int plane) { return dma_bufs_.at(plane)->getSize(); } int DrmBuffer::get_fd() { return getFd(0); } DrmDumbObject* DrmBuffer::get_bo() { return dumb_object_.get(); } DrmBufferProxy::DrmBufferProxy(const VideoBufferInfo& info, const SmartPtr& data) : BufferProxy(info, data) { XCAM_ASSERT(data.ptr()); } DrmDumbObject* DrmBufferProxy::get_bo() { auto data = get_buffer_data(); auto buffer = data.dynamic_cast_ptr(); XCAM_FAIL_RETURN(WARNING, buffer.ptr(), NULL, "DrmBuffer get_buffer_data failed with NULL"); return buffer->get_bo(); } const int DrmBufferProxy::GetFd() { auto data = get_buffer_data(); auto buffer = data.dynamic_cast_ptr(); return buffer->get_fd(); } DrmBufferPool::DrmBufferPool(std::shared_ptr device) : drm_device_(device) {} bool DrmBufferPool::fixate_video_info(VideoBufferInfo& info) { VideoBufferInfo out_info; out_info.init(info.format, info.width, info.height, info.aligned_width, info.aligned_height); info = out_info; return true; } SmartPtr DrmBufferPool::allocate_data(const VideoBufferInfo& buffer_info) { SmartPtr buffer_data; auto bo = drm_device_->CreateDumbObject(buffer_info.aligned_width, buffer_info.aligned_height, buffer_info.color_bits, 1); if (bo != nullptr) { buffer_data = new DrmBuffer(drm_device_, std::move(bo)); } return buffer_data; } SmartPtr DrmBufferPool::create_buffer_from_data(SmartPtr& data) { const VideoBufferInfo& info = get_video_info(); SmartPtr buffer_data = data.dynamic_cast_ptr(); XCAM_ASSERT(buffer_data.ptr()); SmartPtr out_buf = new DrmBufferProxy(info, buffer_data); XCAM_ASSERT(out_buf.ptr()); return out_buf; } } // namespace XCam