1 /*
2 * Copyright (C) 2021–2022 Beijing OSWare Technology Co., Ltd
3 * This file contains confidential and proprietary information of
4 * OSWare Technology Co., Ltd
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 #include "framebuffer_allocator.h"
19 #include <fcntl.h>
20 #include <cerrno>
21 #include <securec.h>
22 #include <linux/fb.h>
23 #include "display_common.h"
24 #include "display_adapter.h"
25 namespace OHOS {
26 namespace HDI {
27 namespace DISPLAY {
SetFdFormatAndVirtualRes(struct fb_var_screeninfo varInfo)28 int32_t FramebufferAllocator::SetFdFormatAndVirtualRes(struct fb_var_screeninfo varInfo)
29 {
30 int ret;
31 DISPLAY_LOGD();
32 varInfo.reserved[0] = 0;
33 varInfo.reserved[1] = 0;
34 varInfo.reserved[2] = 0; // init reserved[2] is 0
35 varInfo.xoffset = 0;
36 varInfo.yoffset = 0;
37 varInfo.activate = FB_ACTIVATE_NOW;
38
39 varInfo.bits_per_pixel = 32; // 32bit
40 varInfo.transp.length = 8; // 8 bits
41 varInfo.red.length = 8; // 8 bits
42 varInfo.green.length = 8; // 8 bits
43 varInfo.blue.length = 8; // 8 bits
44
45 varInfo.transp.offset = 24; // offset 24 of a channel
46 varInfo.red.offset = 0; // offset 16 of red channel
47 varInfo.green.offset = 8; // offset 8 of green channel
48 varInfo.blue.offset = 16; // offset 16 of blue channel
49
50 varInfo.xres_virtual = varInfo.xres;
51 varInfo.yres_virtual = varInfo.yres * FB_BUFFERS_NUM;
52
53 // set framebuffer vary info
54 ret = DisplayAdapter::GetInstance()->Ioctl(deviceFd_, FBIOPUT_VSCREENINFO, &varInfo);
55 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("FBIOPUT_VSCREENINFO failed errno : %d", errno));
56 return DISPLAY_SUCCESS;
57 }
58
InitFb()59 int32_t FramebufferAllocator::InitFb()
60 {
61 int ret;
62 DISPLAY_LOGD();
63 ret = DisplayAdapter::GetInstance()->Ioctl(deviceFd_, FBIOGET_FSCREENINFO, &fixInfo_);
64 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("FBIOGET_FSCREENINFO failed errno : %d", errno));
65
66 ret = DisplayAdapter::GetInstance()->Ioctl(deviceFd_, FBIOGET_VSCREENINFO, &varInfo_);
67 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("FBIOGET_VSCREENINFO failed errno : %d", errno));
68
69 ret = SetFdFormatAndVirtualRes(varInfo_);
70 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE(" failed to set fb format errno : %d", errno));
71
72 // update the variable screen information
73 ret = DisplayAdapter::GetInstance()->Ioctl(deviceFd_, FBIOGET_VSCREENINFO, &varInfo_);
74 DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("FBIOGET_VSCREENINFO failed errno : %d", errno));
75
76 size_t frameBufferSize = fixInfo_.line_length * varInfo_.yres_virtual;
77
78 frameBufferSize_ = frameBufferSize;
79 DISPLAY_CHK_RETURN((varInfo_.yres == 0), DISPLAY_FAILURE, DISPLAY_LOGE("the yres is zero"));
80 buffersNum_ = varInfo_.yres_virtual / varInfo_.yres;
81 bufferSize_ = fixInfo_.line_length * varInfo_.yres;
82 smemStart_ = fixInfo_.smem_start;
83 dmaBufferFb_ = DisplayAdapter::GetInstance()->FbGetDmaBuffer(deviceFd_);
84 DISPLAY_LOGD("the dmabuffer fd of framebuffer is %{public}d", dmaBufferFb_);
85 for (uint32_t i = 0; i < bufferSize_; i++) {
86 freeBuffers_.push(smemStart_ + i * bufferSize_);
87 }
88 DISPLAY_LOGD();
89 return DISPLAY_SUCCESS;
90 }
91
Init()92 int32_t FramebufferAllocator::Init()
93 {
94 DISPLAY_LOGD();
95 if (DisplayAdapter::GetInstance() == nullptr) {
96 DISPLAY_LOGE("framebuffer allocator must depend on the display adapter");
97 return DISPLAY_FAILURE;
98 }
99 deviceFd_ = DisplayAdapter::GetInstance()->OpenDevice(FBDEV_PATH, O_RDWR, 0);
100 if (deviceFd_ < 0) {
101 DISPLAY_LOGE("Failed to open fbdev %{public}d", deviceFd_);
102 return DISPLAY_FAILURE;
103 }
104 return InitFb();
105 }
106
Allocate(const BufferInfo & bufferInfo,BufferHandle & handle)107 int32_t FramebufferAllocator::Allocate(const BufferInfo &bufferInfo, BufferHandle &handle)
108 {
109 DISPLAY_LOGD();
110 if (freeBuffers_.empty()) {
111 DISPLAY_LOGE("has no memory");
112 return DISPLAY_NOMEM;
113 }
114 unsigned long smemAddress = freeBuffers_.front();
115 uint32_t offset = smemAddress - smemStart_;
116
117 handle.phyAddr = smemAddress;
118 handle.fd = DisplayAdapter::GetInstance()->FbGetDmaBuffer(deviceFd_);
119 DISPLAY_LOGD("fd is %{public}d", handle.fd);
120 // temp for use key to save offset
121 handle.key = offset;
122 handle.format = PIXEL_FMT_RGBA_8888;
123 handle.width = bufferInfo.width_;
124 handle.height = bufferInfo.height_;
125 handle.stride = fixInfo_.line_length;
126 handle.size = bufferSize_;
127 handle.usage = bufferInfo.usage_;
128 freeBuffers_.pop();
129 return DISPLAY_SUCCESS;
130 }
131
~FramebufferAllocator()132 FramebufferAllocator::~FramebufferAllocator()
133 {
134 DISPLAY_LOGD();
135 if (deviceFd_ > -1) {
136 DisplayAdapter::GetInstance()->CloseDevice(deviceFd_);
137 deviceFd_ = -1;
138 }
139 }
140
Mmap(BufferHandle & handle)141 void* FramebufferAllocator::Mmap(BufferHandle &handle)
142 {
143 DISPLAY_LOGD();
144 void *virAddr = nullptr;
145 if (handle.virAddr != nullptr) {
146 DISPLAY_LOGW("the buffer has virtual addr");
147 return handle.virAddr;
148 }
149
150 if (handle.fd > -1) {
151 virAddr = mmap(nullptr, frameBufferSize_, PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0);
152 } else {
153 virAddr = mmap(nullptr, frameBufferSize_, PROT_READ | PROT_WRITE, MAP_SHARED, deviceFd_, 0);
154 }
155 if (virAddr == MAP_FAILED) {
156 DISPLAY_LOGE("failed to mmap errno %{public}d", errno);
157 handle.virAddr = nullptr;
158 return nullptr;
159 }
160 handle.virAddr = static_cast<uint8_t*>(virAddr) + handle.key;
161 DISPLAY_LOGD("virAddr %{public}p handle.virAddr %{public}p", handle.virAddr, virAddr);
162
163 return handle.virAddr;
164 }
165
Unmap(BufferHandle & handle)166 int32_t FramebufferAllocator::Unmap(BufferHandle &handle)
167 {
168 DISPLAY_LOGD();
169 if (handle.virAddr == nullptr) {
170 DISPLAY_LOGE("virAddr is nullptr , has not map the buffer");
171 return DISPLAY_PARAM_ERR;
172 }
173 int ret = munmap(static_cast<uint8_t*>(handle.virAddr) - handle.key, frameBufferSize_);
174 if (ret != 0) {
175 DISPLAY_LOGE("munmap failed err: %{public}s", strerror(errno));
176 return DISPLAY_FAILURE;
177 }
178 handle.virAddr = nullptr;
179 return DISPLAY_SUCCESS;
180 }
FreeMem(BufferHandle * handle)181 int32_t FramebufferAllocator::FreeMem(BufferHandle *handle)
182 {
183 DISPLAY_CHK_RETURN((handle == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("handle is nullptr"));
184 freeBuffers_.push(handle->phyAddr);
185 Allocator::FreeMem(handle);
186 return DISPLAY_SUCCESS;
187 }
188 }
189 }
190 }