/*
|
* 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 <drm/drm.h>
|
#include <sys/mman.h>
|
#include <xf86drm.h>
|
|
#include <memory>
|
#include <string>
|
|
#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<DrmDevice>& dev,
|
std::unique_ptr<DrmDumbObject> dumb_object)
|
: drm_device_(std::weak_ptr<DrmDevice>(dev)) {
|
dumb_object_ = std::move(dumb_object);
|
for (int i = 0; i < dumb_object_->num_planes; i++) {
|
dma_bufs_.push_back(std::unique_ptr<DmaBuffer>(
|
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<uint8_t*>(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<DrmBuffer>& data)
|
: BufferProxy(info, data) {
|
XCAM_ASSERT(data.ptr());
|
}
|
|
DrmDumbObject* DrmBufferProxy::get_bo() {
|
auto data = get_buffer_data();
|
auto buffer = data.dynamic_cast_ptr<DrmBuffer>();
|
|
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<DrmBuffer>();
|
|
return buffer->get_fd();
|
}
|
|
DrmBufferPool::DrmBufferPool(std::shared_ptr<DrmDevice> 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<BufferData> DrmBufferPool::allocate_data(const VideoBufferInfo& buffer_info) {
|
SmartPtr<DrmBuffer> 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<BufferProxy> DrmBufferPool::create_buffer_from_data(SmartPtr<BufferData>& data) {
|
const VideoBufferInfo& info = get_video_info();
|
SmartPtr<DrmBuffer> buffer_data = data.dynamic_cast_ptr<DrmBuffer>();
|
XCAM_ASSERT(buffer_data.ptr());
|
|
SmartPtr<DrmBufferProxy> out_buf = new DrmBufferProxy(info, buffer_data);
|
XCAM_ASSERT(out_buf.ptr());
|
return out_buf;
|
}
|
|
} // namespace XCam
|