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
22namespace OHOS {
23BufferManager* BufferManager::GetInstance()
24{
25    static BufferManager instance;
26    return &instance;
27}
28
29bool 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
41bool 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
61bool 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
98BufferHandle* 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
122SurfaceBufferImpl* 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
152SurfaceBufferImpl* 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
172SurfaceBufferImpl* 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
195void 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
217bool 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
251void 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
264int32_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