1 /*
2 * drm_buffer.cpp - DRM Buffer Implementation
3 *
4 * Copyright (c) 2021 Rockchip 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 */
19 #include "drm_buffer.h"
20
21 #include <drm/drm.h>
22 #include <sys/mman.h>
23 #include <xf86drm.h>
24
25 #include <memory>
26 #include <string>
27
28 #include "dma_buffer.h"
29 #include "drm_device.h"
30 #include "xcam_defs.h"
31 #include "xcam_log.h"
32
33 namespace XCam {
34
~DrmBuffer()35 DrmBuffer::~DrmBuffer() {
36 for (auto it = dma_bufs_.begin(); it != dma_bufs_.end();) {
37 dma_bufs_.erase(it);
38 }
39 auto dev = drm_device_.lock();
40 if (dev != nullptr) {
41 dev->DestroyDumbObject(dumb_object_);
42 }
43 }
44
DrmBuffer(const std::shared_ptr<DrmDevice> & dev,std::unique_ptr<DrmDumbObject> dumb_object)45 DrmBuffer::DrmBuffer(const std::shared_ptr<DrmDevice>& dev,
46 std::unique_ptr<DrmDumbObject> dumb_object)
47 : drm_device_(std::weak_ptr<DrmDevice>(dev)) {
48 dumb_object_ = std::move(dumb_object);
49 for (int i = 0; i < dumb_object_->num_planes; i++) {
50 dma_bufs_.push_back(std::unique_ptr<DmaBuffer>(
51 new DmaBuffer(dumb_object_->fds[i], dumb_object_->sizes[i])));
52 }
53 }
54
numPlanes()55 int DrmBuffer::numPlanes() { return dma_bufs_.size(); }
56
map(unsigned int plane)57 uint8_t* DrmBuffer::map(unsigned int plane) {
58 if (plane >= dma_bufs_.size()) {
59 return nullptr;
60 }
61 auto&& buf = dma_bufs_.at(plane);
62 if (!buf->mapped()) {
63 auto dev = drm_device_.lock();
64 dev->RequestMapDumbObject(dumb_object_, plane);
65 }
66 auto ptr = reinterpret_cast<uint8_t*>(buf->map());
67 buf->beginCpuAccess(DmaBufferDirection::kBidirectional);
68 return ptr;
69 }
70
map()71 uint8_t* DrmBuffer::map() { return map(0); }
72
unmap(unsigned int plane)73 bool DrmBuffer::unmap(unsigned int plane) {
74 if (plane >= dma_bufs_.size()) {
75 return false;
76 }
77 auto&& buf = dma_bufs_.at(plane);
78 buf->endCpuAccess(DmaBufferDirection::kBidirectional);
79 buf->unmap();
80 return true;
81 }
82
unmap()83 bool DrmBuffer::unmap() { return unmap(0); }
84
getFd(unsigned int plane)85 int DrmBuffer::getFd(unsigned int plane) {
86 if (plane >= dma_bufs_.size()) {
87 return -1;
88 }
89 return dma_bufs_.at(plane)->getFd();
90 }
91
getSize()92 size_t DrmBuffer::getSize() { return getSize(0); }
93
getSize(unsigned int plane)94 size_t DrmBuffer::getSize(unsigned int plane) { return dma_bufs_.at(plane)->getSize(); }
95
get_fd()96 int DrmBuffer::get_fd() { return getFd(0); }
97
get_bo()98 DrmDumbObject* DrmBuffer::get_bo() { return dumb_object_.get(); }
99
DrmBufferProxy(const VideoBufferInfo & info,const SmartPtr<DrmBuffer> & data)100 DrmBufferProxy::DrmBufferProxy(const VideoBufferInfo& info, const SmartPtr<DrmBuffer>& data)
101 : BufferProxy(info, data) {
102 XCAM_ASSERT(data.ptr());
103 }
104
get_bo()105 DrmDumbObject* DrmBufferProxy::get_bo() {
106 auto data = get_buffer_data();
107 auto buffer = data.dynamic_cast_ptr<DrmBuffer>();
108
109 XCAM_FAIL_RETURN(WARNING, buffer.ptr(), NULL, "DrmBuffer get_buffer_data failed with NULL");
110
111 return buffer->get_bo();
112 }
113
GetFd()114 int DrmBufferProxy::GetFd() {
115 auto data = get_buffer_data();
116 auto buffer = data.dynamic_cast_ptr<DrmBuffer>();
117
118 return buffer->get_fd();
119 }
120
DrmBufferPool(std::shared_ptr<DrmDevice> device)121 DrmBufferPool::DrmBufferPool(std::shared_ptr<DrmDevice> device) : drm_device_(device) {}
122
fixate_video_info(VideoBufferInfo & info)123 bool DrmBufferPool::fixate_video_info(VideoBufferInfo& info) {
124 VideoBufferInfo out_info;
125
126 out_info.init(info.format, info.width, info.height, info.aligned_width, info.aligned_height);
127
128 info = out_info;
129
130 return true;
131 }
132
allocate_data(const VideoBufferInfo & buffer_info)133 SmartPtr<BufferData> DrmBufferPool::allocate_data(const VideoBufferInfo& buffer_info) {
134 SmartPtr<DrmBuffer> buffer_data;
135 auto bo = drm_device_->CreateDumbObject(buffer_info.aligned_width, buffer_info.aligned_height,
136 buffer_info.color_bits, 1);
137 if (bo != nullptr) {
138 buffer_data = new DrmBuffer(drm_device_, std::move(bo));
139 }
140 return buffer_data;
141 }
142
create_buffer_from_data(SmartPtr<BufferData> & data)143 SmartPtr<BufferProxy> DrmBufferPool::create_buffer_from_data(SmartPtr<BufferData>& data) {
144 const VideoBufferInfo& info = get_video_info();
145 SmartPtr<DrmBuffer> buffer_data = data.dynamic_cast_ptr<DrmBuffer>();
146 XCAM_ASSERT(buffer_data.ptr());
147
148 SmartPtr<DrmBufferProxy> out_buf = new DrmBufferProxy(info, buffer_data);
149 XCAM_ASSERT(out_buf.ptr());
150 return out_buf;
151 }
152
153 } // namespace XCam
154