1 /*
2 * Copyright (C) 2020 ARM Limited. All rights reserved.
3 *
4 * Copyright 2016 The Android Open Source Project
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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21 #include <utils/Trace.h>
22
23 #include "Allocator.h"
24 #include "core/mali_gralloc_bufferallocation.h"
25 #include "core/mali_gralloc_bufferdescriptor.h"
26 #include "core/format_info.h"
27 #include "allocator/mali_gralloc_ion.h"
28 #include "gralloc_priv.h"
29 #include "SharedMetadata.h"
30
31 namespace arm
32 {
33 namespace allocator
34 {
35 namespace common
36 {
37
allocate(const buffer_descriptor_t & bufferDescriptor,uint32_t count,IAllocator::allocate_cb hidl_cb,std::function<int (const buffer_descriptor_t *,buffer_handle_t *)> fb_allocator)38 void allocate(const buffer_descriptor_t &bufferDescriptor, uint32_t count, IAllocator::allocate_cb hidl_cb,
39 std::function<int(const buffer_descriptor_t *, buffer_handle_t *)> fb_allocator)
40 {
41 #if DISABLE_FRAMEBUFFER_HAL
42 GRALLOC_UNUSED(fb_allocator);
43 #endif
44 ATRACE_CALL();
45
46 Error error = Error::NONE;
47 int stride = 0;
48 std::vector<hidl_handle> grallocBuffers;
49 gralloc_buffer_descriptor_t grallocBufferDescriptor[1];
50
51 grallocBufferDescriptor[0] = (gralloc_buffer_descriptor_t)(&bufferDescriptor);
52 grallocBuffers.reserve(count);
53
54 for (uint32_t i = 0; i < count; i++)
55 {
56 buffer_handle_t tmpBuffer = nullptr;
57
58 int allocResult;
59 #if (DISABLE_FRAMEBUFFER_HAL != 1)
60 if (((bufferDescriptor.producer_usage & GRALLOC_USAGE_HW_FB) ||
61 (bufferDescriptor.consumer_usage & GRALLOC_USAGE_HW_FB)) &&
62 fb_allocator)
63 {
64 allocResult = fb_allocator(&bufferDescriptor, &tmpBuffer);
65 }
66 else
67 #endif
68 {
69 allocResult = mali_gralloc_buffer_allocate(grallocBufferDescriptor, 1, &tmpBuffer, nullptr);
70 if (allocResult != 0)
71 {
72 MALI_GRALLOC_LOGE("%s, buffer allocation failed with %d", __func__, allocResult);
73 error = Error::NO_RESOURCES;
74 break;
75 }
76 auto hnd = const_cast<private_handle_t *>(reinterpret_cast<const private_handle_t *>(tmpBuffer));
77 hnd->imapper_version = HIDL_MAPPER_VERSION_SCALED;
78
79 // 4k is rougly 7.9 MB with one byte per pixel. We are
80 // assuming that the reserved region might be needed for
81 // dynamic HDR and that represents the largest size.
82 uint64_t max_reserved_region_size = 8ull * 1024 * 1024;
83 hnd->reserved_region_size = bufferDescriptor.reserved_size;
84 if (hnd->reserved_region_size > max_reserved_region_size) {
85 MALI_GRALLOC_LOGE("%s, Requested reserved region size (%" PRIu64 ") is larger than allowed (%" PRIu64 ")",
86 __func__, hnd->reserved_region_size, max_reserved_region_size);
87 error = Error::BAD_VALUE;
88 break;
89 }
90 hnd->attr_size = mapper::common::shared_metadata_size() + hnd->reserved_region_size;
91
92 if (hnd->get_usage() & GRALLOC_USAGE_ROIINFO)
93 {
94 hnd->attr_size += 32768;
95 }
96
97 /* TODO: must do error checking */
98 mali_gralloc_ion_allocate_attr(hnd);
99
100 /* TODO: error check for failure */
101 void* metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE,
102 MAP_SHARED, hnd->get_share_attr_fd(), 0);
103
104 memset(metadata_vaddr, 0, hnd->attr_size);
105
106 mapper::common::shared_metadata_init(metadata_vaddr, bufferDescriptor.name);
107
108 const uint32_t base_format = bufferDescriptor.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
109 const uint64_t usage = bufferDescriptor.consumer_usage | bufferDescriptor.producer_usage;
110 android_dataspace_t dataspace;
111 get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace);
112
113 // TODO: set_dataspace API in mapper expects a buffer to be first imported before it can set the dataspace
114 {
115 using mapper::common::shared_metadata;
116 using mapper::common::aligned_optional;
117 using mapper::common::Dataspace;
118 (static_cast<shared_metadata*>(metadata_vaddr))->dataspace = aligned_optional(static_cast<Dataspace>(dataspace));
119 }
120
121 munmap(metadata_vaddr, hnd->attr_size);
122 }
123
124 int tmpStride = 0;
125 tmpStride = bufferDescriptor.pixel_stride;
126
127 if (stride == 0)
128 {
129 stride = tmpStride;
130 }
131 else if (stride != tmpStride)
132 {
133 /* Stride must be the same for all allocations */
134 mali_gralloc_buffer_free(tmpBuffer);
135 stride = 0;
136 error = Error::UNSUPPORTED;
137 break;
138 }
139
140 grallocBuffers.emplace_back(hidl_handle(tmpBuffer));
141 }
142
143 /* Populate the array of buffers for application consumption */
144 hidl_vec<hidl_handle> hidlBuffers;
145 if (error == Error::NONE)
146 {
147 hidlBuffers.setToExternal(grallocBuffers.data(), grallocBuffers.size());
148 }
149 hidl_cb(error, stride, hidlBuffers);
150
151 /* The application should import the Gralloc buffers using IMapper for
152 * further usage. Free the allocated buffers in IAllocator context
153 */
154 for (const auto &buffer : grallocBuffers)
155 {
156 mali_gralloc_buffer_free(buffer.getNativeHandle());
157 }
158 }
159
160 } // namespace common
161 } // namespace allocator
162 } // namespace arm
163