blob: 07ad4c107f3a7d72a3bc358e64f1605d812bd601 [file] [log] [blame]
Dan Stozad3182402014-11-17 12:03:59 -08001/*
Mathias Agopian076b1cc2009-04-10 14:24:30 -07002**
3** Copyright 2009, The Android Open Source Project
4**
Dan Stozad3182402014-11-17 12:03:59 -08005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
Mathias Agopian076b1cc2009-04-10 14:24:30 -07008**
Dan Stozad3182402014-11-17 12:03:59 -08009** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopian076b1cc2009-04-10 14:24:30 -070010**
Dan Stozad3182402014-11-17 12:03:59 -080011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
Mathias Agopian076b1cc2009-04-10 14:24:30 -070015** limitations under the License.
16*/
17
Mathias Agopian5629eb12010-04-15 14:57:39 -070018#define LOG_TAG "GraphicBufferAllocator"
Mathias Agopiancf563192012-02-29 20:43:29 -080019#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Mathias Agopian5629eb12010-04-15 14:57:39 -070020
Mark Salyzyn7823e122016-09-29 08:08:05 -070021#include <log/log.h>
Mathias Agopian4243e662009-04-15 18:34:24 -070022#include <utils/Singleton.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070023#include <utils/String8.h>
Mathias Agopiancf563192012-02-29 20:43:29 -080024#include <utils/Trace.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070025
Mathias Agopian3330b202009-10-05 17:07:12 -070026#include <ui/GraphicBufferAllocator.h>
Dan Stoza8deb4da2016-06-01 18:21:44 -070027#include <ui/Gralloc1On0Adapter.h>
Chia-I Wu9ba189d2016-09-22 17:13:08 +080028#include <ui/GrallocAllocator.h>
29#include <ui/GrallocMapper.h>
30#include <ui/GraphicBufferMapper.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070031
Mathias Agopian076b1cc2009-04-10 14:24:30 -070032namespace android {
33// ---------------------------------------------------------------------------
34
Mathias Agopian3330b202009-10-05 17:07:12 -070035ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator )
Mathias Agopian4243e662009-04-15 18:34:24 -070036
Mathias Agopian3330b202009-10-05 17:07:12 -070037Mutex GraphicBufferAllocator::sLock;
Mathias Agopianb26af232009-10-05 18:19:57 -070038KeyedVector<buffer_handle_t,
39 GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070040
Mathias Agopian3330b202009-10-05 17:07:12 -070041GraphicBufferAllocator::GraphicBufferAllocator()
Chia-I Wu9ba189d2016-09-22 17:13:08 +080042 : mAllocator(std::make_unique<Gralloc2::Allocator>()),
43 mMapper(GraphicBufferMapper::getInstance())
44{
45 if (!mAllocator->valid()) {
46 mLoader = std::make_unique<Gralloc1::Loader>();
47 mDevice = mLoader->getDevice();
48 }
49}
Mathias Agopian076b1cc2009-04-10 14:24:30 -070050
Dan Stoza8deb4da2016-06-01 18:21:44 -070051GraphicBufferAllocator::~GraphicBufferAllocator() {}
Mathias Agopian076b1cc2009-04-10 14:24:30 -070052
Mathias Agopian3330b202009-10-05 17:07:12 -070053void GraphicBufferAllocator::dump(String8& result) const
Mathias Agopian076b1cc2009-04-10 14:24:30 -070054{
55 Mutex::Autolock _l(sLock);
56 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
57 size_t total = 0;
Erik Gilling1d21a9c2010-12-01 16:38:01 -080058 const size_t SIZE = 4096;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070059 char buffer[SIZE];
60 snprintf(buffer, SIZE, "Allocated buffers:\n");
61 result.append(buffer);
62 const size_t c = list.size();
63 for (size_t i=0 ; i<c ; i++) {
64 const alloc_rec_t& rec(list.valueAt(i));
Mathias Agopiana947de82011-07-29 16:35:41 -070065 if (rec.size) {
Craig Donner6ebc46a2016-10-21 15:23:44 -070066 snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%08x | %s\n",
George Burgess IV1093cf32017-01-25 17:09:18 -080067 list.keyAt(i), rec.size/1024.0,
Craig Donner6ebc46a2016-10-21 15:23:44 -070068 rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
69 rec.usage, rec.requestorName.c_str());
Mathias Agopiana947de82011-07-29 16:35:41 -070070 } else {
Craig Donner6ebc46a2016-10-21 15:23:44 -070071 snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %4u | %8X | 0x%08x | %s\n",
Mathias Agopiana947de82011-07-29 16:35:41 -070072 list.keyAt(i),
Craig Donner6ebc46a2016-10-21 15:23:44 -070073 rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
74 rec.usage, rec.requestorName.c_str());
Mathias Agopiana947de82011-07-29 16:35:41 -070075 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -070076 result.append(buffer);
77 total += rec.size;
78 }
George Burgess IV1093cf32017-01-25 17:09:18 -080079 snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0);
Mathias Agopian076b1cc2009-04-10 14:24:30 -070080 result.append(buffer);
Chia-I Wu9ba189d2016-09-22 17:13:08 +080081
82 std::string deviceDump;
83 if (mAllocator->valid()) {
84 deviceDump = mAllocator->dumpDebugInfo();
85 } else {
86 deviceDump = mDevice->dump();
87 }
88
Dan Stoza8deb4da2016-06-01 18:21:44 -070089 result.append(deviceDump.c_str(), deviceDump.size());
Mathias Agopian076b1cc2009-04-10 14:24:30 -070090}
91
Mathias Agopian678bdd62010-12-03 17:33:09 -080092void GraphicBufferAllocator::dumpToSystemLog()
93{
94 String8 s;
95 GraphicBufferAllocator::getInstance().dump(s);
Steve Block9d453682011-12-20 16:23:08 +000096 ALOGD("%s", s.string());
Mathias Agopian678bdd62010-12-03 17:33:09 -080097}
98
Chia-I Wu9ba189d2016-09-22 17:13:08 +080099namespace {
100
101class HalBuffer {
102public:
103 HalBuffer(const Gralloc2::Allocator* allocator,
104 uint32_t width, uint32_t height,
Craig Donner6ebc46a2016-10-21 15:23:44 -0700105 PixelFormat format, uint32_t layerCount, uint32_t usage)
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800106 : mAllocator(allocator), mBufferValid(false)
107 {
Chia-I Wub018bf02016-11-22 13:29:49 +0800108 Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800109 info.width = width;
110 info.height = height;
111 info.format = static_cast<Gralloc2::PixelFormat>(format);
Craig Donner6ebc46a2016-10-21 15:23:44 -0700112 info.layerCount = layerCount;
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800113 info.producerUsageMask = usage;
114 info.consumerUsageMask = usage;
115
116 Gralloc2::BufferDescriptor descriptor;
Chia-I Wu67e376d2016-12-19 11:36:22 +0800117 auto error = mAllocator->createBufferDescriptor(info, &descriptor);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800118 if (error != Gralloc2::Error::NONE) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700119 ALOGE("Failed to create desc (%u x %u) layerCount %u format %d usage %u: %d",
120 width, height, layerCount, format, usage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800121 return;
122 }
123
Chia-I Wu67e376d2016-12-19 11:36:22 +0800124 error = mAllocator->allocate(descriptor, &mBuffer);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800125 if (error == Gralloc2::Error::NOT_SHARED) {
126 error = Gralloc2::Error::NONE;
127 }
128
129 if (error != Gralloc2::Error::NONE) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700130 ALOGE("Failed to allocate (%u x %u) layerCount %u format %d usage %u: %d",
131 width, height, layerCount, format, usage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800132 mAllocator->destroyBufferDescriptor(descriptor);
133 return;
134 }
135
Chia-I Wu67e376d2016-12-19 11:36:22 +0800136 error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800137 if (error != Gralloc2::Error::NONE) {
138 ALOGE("Failed to export handle");
139 mAllocator->free(mBuffer);
140 mAllocator->destroyBufferDescriptor(descriptor);
141 return;
142 }
143
144 mAllocator->destroyBufferDescriptor(descriptor);
145
146 mBufferValid = true;
147 }
148
149 ~HalBuffer()
150 {
151 if (mBufferValid) {
152 if (mHandle) {
153 native_handle_close(mHandle);
154 native_handle_delete(mHandle);
155 }
156
157 mAllocator->free(mBuffer);
158 }
159 }
160
161 bool exportHandle(GraphicBufferMapper& mapper,
162 buffer_handle_t* handle, uint32_t* stride)
163 {
164 if (!mBufferValid) {
165 return false;
166 }
167
168 if (mapper.registerBuffer(mHandle)) {
169 return false;
170 }
171
172 *handle = mHandle;
173
Chia-I Wu67e376d2016-12-19 11:36:22 +0800174 auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800175 if (error != Gralloc2::Error::NONE) {
176 ALOGW("Failed to get stride from buffer: %d", error);
177 *stride = 0;
178 }
179
180 mHandle = nullptr;
181 mAllocator->free(mBuffer);
182 mBufferValid = false;
183
184 return true;
185 }
186
187private:
188 const Gralloc2::Allocator* mAllocator;
189
190 bool mBufferValid;
191 Gralloc2::Buffer mBuffer;
192 native_handle_t* mHandle;
193};
194
195} // namespace
196
Dan Stoza8deb4da2016-06-01 18:21:44 -0700197status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
Craig Donner6ebc46a2016-10-21 15:23:44 -0700198 PixelFormat format, uint32_t layerCount, uint32_t usage,
199 buffer_handle_t* handle, uint32_t* stride, uint64_t graphicBufferId,
200 std::string requestorName)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700201{
Mathias Agopiancf563192012-02-29 20:43:29 -0800202 ATRACE_CALL();
Dan Stozad3182402014-11-17 12:03:59 -0800203
Mathias Agopian5629eb12010-04-15 14:57:39 -0700204 // make sure to not allocate a N x 0 or 0 x N buffer, since this is
205 // allowed from an API stand-point allocate a 1x1 buffer instead.
Dan Stozad3182402014-11-17 12:03:59 -0800206 if (!width || !height)
207 width = height = 1;
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700208
Craig Donner6ebc46a2016-10-21 15:23:44 -0700209 // Ensure that layerCount is valid.
210 if (layerCount < 1)
211 layerCount = 1;
212
Dan Stoza24fa67f2015-05-29 12:48:04 -0700213 // Filter out any usage bits that should not be passed to the gralloc module
214 usage &= GRALLOC_USAGE_ALLOC_MASK;
215
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800216 gralloc1_error_t error;
217 if (mAllocator->valid()) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700218 HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
219 usage);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800220 if (!buffer.exportHandle(mMapper, handle, stride)) {
221 return NO_MEMORY;
222 }
223 error = GRALLOC1_ERROR_NONE;
224 } else {
225 auto descriptor = mDevice->createDescriptor();
226 error = descriptor->setDimensions(width, height);
227 if (error != GRALLOC1_ERROR_NONE) {
228 ALOGE("Failed to set dimensions to (%u, %u): %d",
229 width, height, error);
230 return BAD_VALUE;
231 }
232 error = descriptor->setFormat(
233 static_cast<android_pixel_format_t>(format));
234 if (error != GRALLOC1_ERROR_NONE) {
235 ALOGE("Failed to set format to %d: %d", format, error);
236 return BAD_VALUE;
237 }
Craig Donner6ebc46a2016-10-21 15:23:44 -0700238 if (mDevice->hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
239 error = descriptor->setLayerCount(layerCount);
240 if (error != GRALLOC1_ERROR_NONE) {
241 ALOGE("Failed to set layer count to %u: %d", layerCount, error);
242 return BAD_VALUE;
243 }
244 } else if (layerCount > 1) {
245 ALOGE("Failed to set layer count to %u: capability unsupported",
246 layerCount);
247 return BAD_VALUE;
248 }
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800249 error = descriptor->setProducerUsage(
250 static_cast<gralloc1_producer_usage_t>(usage));
251 if (error != GRALLOC1_ERROR_NONE) {
252 ALOGE("Failed to set producer usage to %u: %d", usage, error);
253 return BAD_VALUE;
254 }
255 error = descriptor->setConsumerUsage(
256 static_cast<gralloc1_consumer_usage_t>(usage));
257 if (error != GRALLOC1_ERROR_NONE) {
258 ALOGE("Failed to set consumer usage to %u: %d", usage, error);
259 return BAD_VALUE;
260 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700261
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800262 error = mDevice->allocate(descriptor, graphicBufferId, handle);
263 if (error != GRALLOC1_ERROR_NONE) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700264 ALOGE("Failed to allocate (%u x %u) layerCount %u format %d usage %u: %d",
265 width, height, layerCount, format, usage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800266 return NO_MEMORY;
267 }
Dan Stozad3182402014-11-17 12:03:59 -0800268
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800269 error = mDevice->getStride(*handle, stride);
270 if (error != GRALLOC1_ERROR_NONE) {
271 ALOGW("Failed to get stride from buffer: %d", error);
272 }
Dan Stoza8deb4da2016-06-01 18:21:44 -0700273 }
274
275 if (error == NO_ERROR) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700276 Mutex::Autolock _l(sLock);
277 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
Dan Stozad3182402014-11-17 12:03:59 -0800278 uint32_t bpp = bytesPerPixel(format);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700279 alloc_rec_t rec;
Dan Stozad3182402014-11-17 12:03:59 -0800280 rec.width = width;
281 rec.height = height;
282 rec.stride = *stride;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700283 rec.format = format;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700284 rec.layerCount = layerCount;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700285 rec.usage = usage;
Dan Stozad3182402014-11-17 12:03:59 -0800286 rec.size = static_cast<size_t>(height * (*stride) * bpp);
Dan Stoza024e9312016-08-24 12:17:29 -0700287 rec.requestorName = std::move(requestorName);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700288 list.add(*handle, rec);
289 }
290
Dan Stoza8deb4da2016-06-01 18:21:44 -0700291 return NO_ERROR;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700292}
293
Mathias Agopian3330b202009-10-05 17:07:12 -0700294status_t GraphicBufferAllocator::free(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700295{
Mathias Agopiancf563192012-02-29 20:43:29 -0800296 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -0800297
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800298 gralloc1_error_t error;
299 if (mAllocator->valid()) {
300 error = static_cast<gralloc1_error_t>(
301 mMapper.unregisterBuffer(handle));
302 } else {
303 error = mDevice->release(handle);
304 }
305
Dan Stoza8deb4da2016-06-01 18:21:44 -0700306 if (error != GRALLOC1_ERROR_NONE) {
307 ALOGE("Failed to free buffer: %d", error);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700308 }
309
Dan Stoza8deb4da2016-06-01 18:21:44 -0700310 Mutex::Autolock _l(sLock);
311 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
312 list.removeItem(handle);
313
314 return NO_ERROR;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700315}
316
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700317// ---------------------------------------------------------------------------
318}; // namespace android