1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "buffer_manager.h"
17 
18 #include "buffer_common.h"
19 #include "securec.h"
20 #include "surface_buffer.h"
21 
22 namespace OHOS {
GetInstance()23 BufferManager* BufferManager::GetInstance()
24 {
25     static BufferManager instance;
26     return &instance;
27 }
28 
Init()29 bool BufferManager::Init()
30 {
31     if (grallocFucs_ != nullptr) {
32         GRAPHIC_LOGI("BufferManager has init succeed.");
33         return true;
34     }
35     if (GrallocInitialize(&grallocFucs_) != DISPLAY_SUCCESS) {
36         return false;
37     }
38     return true;
39 }
40 
ConvertUsage(uint64_t & destUsage,uint32_t srcUsage) const41 bool BufferManager::ConvertUsage(uint64_t& destUsage, uint32_t srcUsage) const
42 {
43     switch (srcUsage) {
44         case BUFFER_CONSUMER_USAGE_SORTWARE:
45             destUsage = HBM_USE_MEM_SHARE;
46             break;
47         case BUFFER_CONSUMER_USAGE_HARDWARE:
48         case BUFFER_CONSUMER_USAGE_HARDWARE_PRODUCER_CACHE:
49             destUsage = HBM_USE_MEM_MMZ;
50             break;
51         case BUFFER_CONSUMER_USAGE_HARDWARE_CONSUMER_CACHE:
52             destUsage = HBM_USE_MEM_MMZ_CACHE;
53             break;
54         default:
55             GRAPHIC_LOGW("Conversion usage failed.");
56             return false;
57     }
58     return true;
59 }
60 
ConvertFormat(PixelFormat & destFormat,uint32_t srcFormat) const61 bool BufferManager::ConvertFormat(PixelFormat& destFormat, uint32_t srcFormat) const
62 {
63     switch (srcFormat) {
64         case IMAGE_PIXEL_FORMAT_NONE:
65             destFormat = PIXEL_FMT_BUTT;
66             break;
67         case IMAGE_PIXEL_FORMAT_RGB565:
68             destFormat = PIXEL_FMT_RGB_565;
69             break;
70         case IMAGE_PIXEL_FORMAT_ARGB1555:
71             destFormat = PIXEL_FMT_RGBA_5551;
72             break;
73         case IMAGE_PIXEL_FORMAT_RGB888:
74             destFormat = PIXEL_FMT_RGB_888;
75             break;
76         case IMAGE_PIXEL_FORMAT_ARGB8888:
77             destFormat = PIXEL_FMT_RGBA_8888;
78             break;
79         case IMAGE_PIXEL_FORMAT_NV12:
80             destFormat = PIXEL_FMT_YCBCR_420_SP;
81             break;
82         case IMAGE_PIXEL_FORMAT_NV21:
83             destFormat = PIXEL_FMT_YCRCB_420_SP;
84             break;
85         case IMAGE_PIXEL_FORMAT_YUV420:
86             destFormat = PIXEL_FMT_YCBCR_420_P;
87             break;
88         case IMAGE_PIXEL_FORMAT_YVU420:
89             destFormat = PIXEL_FMT_YCRCB_420_P;
90             break;
91         default:
92             GRAPHIC_LOGW("Conversion format failed.");
93             return false;
94     }
95     return true;
96 }
97 
AllocateBufferHandle(SurfaceBufferImpl & buffer) const98 BufferHandle* BufferManager::AllocateBufferHandle(SurfaceBufferImpl& buffer) const
99 {
100     uint32_t total = buffer.GetReserveFds() + buffer.GetReserveInts() + sizeof(BufferHandle);
101     BufferHandle* bufferHandle = static_cast<BufferHandle *>(malloc(total));
102     if (bufferHandle != nullptr) {
103         bufferHandle->fd = buffer.GetKey();
104         bufferHandle->phyAddr = buffer.GetPhyAddr();
105         bufferHandle->size = buffer.GetSize();
106         if (!ConvertUsage(bufferHandle->usage, buffer.GetUsage())) {
107             GRAPHIC_LOGW("Conversion usage failed.");
108             free(bufferHandle);
109             return nullptr;
110         }
111         bufferHandle->virAddr = buffer.GetVirAddr();
112         bufferHandle->reserveFds = buffer.GetReserveFds();
113         bufferHandle->reserveInts = buffer.GetReserveInts();
114         for (uint32_t i = 0; i < (buffer.GetReserveFds() + buffer.GetReserveInts()); i++) {
115             buffer.GetInt32(i, bufferHandle->reserve[i]);
116         }
117         return bufferHandle;
118     }
119     return nullptr;
120 }
121 
AllocBuffer(AllocInfo info)122 SurfaceBufferImpl* BufferManager::AllocBuffer(AllocInfo info)
123 {
124     RETURN_VAL_IF_FAIL((grallocFucs_ != nullptr), nullptr);
125     BufferHandle* bufferHandle = nullptr;
126     if ((grallocFucs_->AllocMem == nullptr) || (grallocFucs_->AllocMem(&info, &bufferHandle) != DISPLAY_SUCCESS)) {
127         GRAPHIC_LOGE("Alloc graphic buffer failed");
128         return nullptr;
129     }
130     SurfaceBufferImpl* buffer = new SurfaceBufferImpl();
131     if (buffer != nullptr) {
132         buffer->SetMaxSize(bufferHandle->size);
133         buffer->SetVirAddr(bufferHandle->virAddr);
134         buffer->SetKey(bufferHandle->fd);
135         buffer->SetPhyAddr(bufferHandle->phyAddr);
136         buffer->SetStride(bufferHandle->stride);
137         buffer->SetReserveFds(bufferHandle->reserveFds);
138         buffer->SetReserveInts(bufferHandle->reserveInts);
139         for (uint32_t i = 0; i < (bufferHandle->reserveFds + bufferHandle->reserveInts); i++) {
140             buffer->SetInt32(i, bufferHandle->reserve[i]);
141         }
142         BufferKey key = {bufferHandle->fd, bufferHandle->phyAddr};
143         bufferHandleMap_.insert(std::make_pair(key, bufferHandle));
144         GRAPHIC_LOGD("Alloc buffer succeed to shared memory segment.");
145     } else {
146         grallocFucs_->FreeMem(bufferHandle);
147         GRAPHIC_LOGW("Alloc buffer failed to shared memory segment.");
148     }
149     return buffer;
150 }
151 
AllocBuffer(uint32_t size,uint32_t usage)152 SurfaceBufferImpl* BufferManager::AllocBuffer(uint32_t size, uint32_t usage)
153 {
154     RETURN_VAL_IF_FAIL((grallocFucs_ != nullptr), nullptr);
155     AllocInfo info = {0};
156     info.expectedSize = size;
157     info.format = PIXEL_FMT_RGB_565;
158     if (!ConvertUsage(info.usage, usage)) {
159         GRAPHIC_LOGW("Alloc graphic buffer failed --- conversion usage.");
160         return nullptr;
161     }
162     info.usage |= HBM_USE_ASSIGN_SIZE;
163     SurfaceBufferImpl* buffer = AllocBuffer(info);
164     if (buffer == nullptr) {
165         GRAPHIC_LOGE("Alloc graphic buffer failed");
166         return nullptr;
167     }
168     buffer->SetUsage(usage);
169     return buffer;
170 }
171 
AllocBuffer(uint32_t width,uint32_t height,uint32_t format,uint32_t usage)172 SurfaceBufferImpl* BufferManager::AllocBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage)
173 {
174     RETURN_VAL_IF_FAIL((grallocFucs_ != nullptr), nullptr);
175     AllocInfo info = {0};
176     info.width = width;
177     info.height = height;
178     if (!ConvertUsage(info.usage, usage)) {
179         GRAPHIC_LOGW("Alloc graphic buffer failed --- conversion usage.");
180         return nullptr;
181     }
182     if (!ConvertFormat(info.format, format)) {
183         GRAPHIC_LOGW("Alloc graphic buffer failed --- conversion format.");
184         return nullptr;
185     }
186     SurfaceBufferImpl* buffer = AllocBuffer(info);
187     if (buffer == nullptr) {
188         GRAPHIC_LOGE("Alloc graphic buffer failed");
189         return nullptr;
190     }
191     buffer->SetUsage(usage);
192     return buffer;
193 }
194 
FreeBuffer(SurfaceBufferImpl ** buffer)195 void BufferManager::FreeBuffer(SurfaceBufferImpl** buffer)
196 {
197     RETURN_IF_FAIL((grallocFucs_ != nullptr));
198     if ((*buffer) == nullptr) {
199         GRAPHIC_LOGW("Input param buffer is null.");
200         return;
201     }
202     BufferKey key = {(*buffer)->GetKey(), (*buffer)->GetPhyAddr()};
203     auto iter = bufferHandleMap_.find(key);
204     if (iter == bufferHandleMap_.end()) {
205         return;
206     }
207     BufferHandle* bufferHandle = iter->second;
208     if (grallocFucs_->FreeMem != nullptr) {
209         grallocFucs_->FreeMem(bufferHandle);
210         bufferHandleMap_.erase(key);
211         delete *buffer;
212         *buffer = nullptr;
213         GRAPHIC_LOGD("Free buffer succeed.");
214     }
215 }
216 
MapBuffer(SurfaceBufferImpl & buffer) const217 bool BufferManager::MapBuffer(SurfaceBufferImpl& buffer) const
218 {
219     RETURN_VAL_IF_FAIL((grallocFucs_ != nullptr), false);
220     void* virAddr = nullptr;
221     BufferHandle* bufferHandle = AllocateBufferHandle(buffer);
222     if (bufferHandle == nullptr) {
223         return false;
224     }
225     if (buffer.GetUsage() == BUFFER_CONSUMER_USAGE_HARDWARE ||
226         buffer.GetUsage() == BUFFER_CONSUMER_USAGE_HARDWARE_CONSUMER_CACHE ||
227         buffer.GetUsage() == BUFFER_CONSUMER_USAGE_SORTWARE) {
228         if (grallocFucs_->Mmap != nullptr) {
229             virAddr = grallocFucs_->Mmap(bufferHandle);
230         }
231     } else if (buffer.GetUsage() == BUFFER_CONSUMER_USAGE_HARDWARE_PRODUCER_CACHE) {
232         if (grallocFucs_->MmapCache != nullptr) {
233             virAddr = grallocFucs_->MmapCache(bufferHandle);
234         }
235     } else {
236         GRAPHIC_LOGE("No support usage.");
237         free(bufferHandle);
238         return false;
239     }
240     if (virAddr == nullptr) {
241         GRAPHIC_LOGE("Map Buffer error.");
242         free(bufferHandle);
243         return false;
244     }
245     buffer.SetVirAddr(virAddr);
246     GRAPHIC_LOGD("Map Buffer succeed.");
247     free(bufferHandle);
248     return true;
249 }
250 
UnmapBuffer(SurfaceBufferImpl & buffer) const251 void BufferManager::UnmapBuffer(SurfaceBufferImpl& buffer) const
252 {
253     RETURN_IF_FAIL((grallocFucs_ != nullptr));
254     BufferHandle* bufferHandle = AllocateBufferHandle(buffer);
255     if (bufferHandle == nullptr) {
256         return;
257     }
258     if ((grallocFucs_->Unmap == nullptr) || (grallocFucs_->Unmap(bufferHandle) != DISPLAY_SUCCESS)) {
259         GRAPHIC_LOGE("Umap buffer failed.");
260     }
261     free(bufferHandle);
262 }
263 
FlushCache(SurfaceBufferImpl & buffer) const264 int32_t BufferManager::FlushCache(SurfaceBufferImpl& buffer) const
265 {
266     RETURN_VAL_IF_FAIL((grallocFucs_ != nullptr), SURFACE_ERROR_NOT_READY);
267     BufferHandle* bufferHandle = AllocateBufferHandle(buffer);
268     if (bufferHandle == nullptr) {
269         return -1;
270     }
271     if (buffer.GetUsage() == BUFFER_CONSUMER_USAGE_HARDWARE_CONSUMER_CACHE) {
272         if ((grallocFucs_->FlushCache == nullptr) || (grallocFucs_->FlushCache(bufferHandle) != DISPLAY_SUCCESS)) {
273             GRAPHIC_LOGE("Flush cache buffer failed.");
274         }
275     } else if (buffer.GetUsage() == BUFFER_CONSUMER_USAGE_HARDWARE_PRODUCER_CACHE) {
276         if ((grallocFucs_->FlushMCache == nullptr) || (grallocFucs_->FlushMCache(bufferHandle) != DISPLAY_SUCCESS)) {
277             GRAPHIC_LOGE("Flush M cache buffer failed.");
278         }
279     }
280     free(bufferHandle);
281     return SURFACE_ERROR_OK;
282 }
283 } // namespace OHOS
284