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