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