blob: 3f18bbc32c34d9acf3b2e406a7b33b677a31dd62 [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
Mathias Agopianfe2f54f2017-02-15 19:48:58 -080021#include <ui/GraphicBufferAllocator.h>
22
23#include <stdio.h>
24
Mark Salyzyn7823e122016-09-29 08:08:05 -070025#include <log/log.h>
Mathias Agopian4243e662009-04-15 18:34:24 -070026#include <utils/Singleton.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070027#include <utils/String8.h>
Mathias Agopiancf563192012-02-29 20:43:29 -080028#include <utils/Trace.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070029
Chia-I Wu9ba189d2016-09-22 17:13:08 +080030#include <ui/GrallocAllocator.h>
31#include <ui/GrallocMapper.h>
32#include <ui/GraphicBufferMapper.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070033
Mathias Agopian076b1cc2009-04-10 14:24:30 -070034namespace android {
35// ---------------------------------------------------------------------------
36
Mathias Agopian3330b202009-10-05 17:07:12 -070037ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator )
Mathias Agopian4243e662009-04-15 18:34:24 -070038
Mathias Agopian3330b202009-10-05 17:07:12 -070039Mutex GraphicBufferAllocator::sLock;
Mathias Agopianb26af232009-10-05 18:19:57 -070040KeyedVector<buffer_handle_t,
41 GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070042
Mathias Agopian3330b202009-10-05 17:07:12 -070043GraphicBufferAllocator::GraphicBufferAllocator()
Chia-I Wu9ba189d2016-09-22 17:13:08 +080044 : mAllocator(std::make_unique<Gralloc2::Allocator>()),
45 mMapper(GraphicBufferMapper::getInstance())
46{
47 if (!mAllocator->valid()) {
48 mLoader = std::make_unique<Gralloc1::Loader>();
49 mDevice = mLoader->getDevice();
50 }
51}
Mathias Agopian076b1cc2009-04-10 14:24:30 -070052
Dan Stoza8deb4da2016-06-01 18:21:44 -070053GraphicBufferAllocator::~GraphicBufferAllocator() {}
Mathias Agopian076b1cc2009-04-10 14:24:30 -070054
Mathias Agopian3330b202009-10-05 17:07:12 -070055void GraphicBufferAllocator::dump(String8& result) const
Mathias Agopian076b1cc2009-04-10 14:24:30 -070056{
57 Mutex::Autolock _l(sLock);
58 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
59 size_t total = 0;
Erik Gilling1d21a9c2010-12-01 16:38:01 -080060 const size_t SIZE = 4096;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070061 char buffer[SIZE];
62 snprintf(buffer, SIZE, "Allocated buffers:\n");
63 result.append(buffer);
64 const size_t c = list.size();
65 for (size_t i=0 ; i<c ; i++) {
66 const alloc_rec_t& rec(list.valueAt(i));
Mathias Agopiana947de82011-07-29 16:35:41 -070067 if (rec.size) {
Craig Donnere96a3252017-02-02 12:13:34 -080068 snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64
69 ", 0x%" PRIx64 " | %s\n",
George Burgess IV1093cf32017-01-25 17:09:18 -080070 list.keyAt(i), rec.size/1024.0,
Craig Donner6ebc46a2016-10-21 15:23:44 -070071 rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
Craig Donnere96a3252017-02-02 12:13:34 -080072 rec.producerUsage, rec.consumerUsage,
73 rec.requestorName.c_str());
Mathias Agopiana947de82011-07-29 16:35:41 -070074 } else {
Craig Donnere96a3252017-02-02 12:13:34 -080075 snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64
76 ", 0x%" PRIx64 " | %s\n",
Mathias Agopiana947de82011-07-29 16:35:41 -070077 list.keyAt(i),
Craig Donner6ebc46a2016-10-21 15:23:44 -070078 rec.width, rec.stride, rec.height, rec.layerCount, rec.format,
Craig Donnere96a3252017-02-02 12:13:34 -080079 rec.producerUsage, rec.consumerUsage,
80 rec.requestorName.c_str());
Mathias Agopiana947de82011-07-29 16:35:41 -070081 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -070082 result.append(buffer);
83 total += rec.size;
84 }
George Burgess IV1093cf32017-01-25 17:09:18 -080085 snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0);
Mathias Agopian076b1cc2009-04-10 14:24:30 -070086 result.append(buffer);
Chia-I Wu9ba189d2016-09-22 17:13:08 +080087
88 std::string deviceDump;
89 if (mAllocator->valid()) {
90 deviceDump = mAllocator->dumpDebugInfo();
91 } else {
92 deviceDump = mDevice->dump();
93 }
94
Dan Stoza8deb4da2016-06-01 18:21:44 -070095 result.append(deviceDump.c_str(), deviceDump.size());
Mathias Agopian076b1cc2009-04-10 14:24:30 -070096}
97
Mathias Agopian678bdd62010-12-03 17:33:09 -080098void GraphicBufferAllocator::dumpToSystemLog()
99{
100 String8 s;
101 GraphicBufferAllocator::getInstance().dump(s);
Steve Block9d453682011-12-20 16:23:08 +0000102 ALOGD("%s", s.string());
Mathias Agopian678bdd62010-12-03 17:33:09 -0800103}
104
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800105namespace {
106
107class HalBuffer {
108public:
109 HalBuffer(const Gralloc2::Allocator* allocator,
110 uint32_t width, uint32_t height,
Craig Donnere96a3252017-02-02 12:13:34 -0800111 PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
112 uint64_t consumerUsage)
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800113 : mAllocator(allocator), mBufferValid(false)
114 {
Chia-I Wub018bf02016-11-22 13:29:49 +0800115 Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800116 info.width = width;
117 info.height = height;
118 info.format = static_cast<Gralloc2::PixelFormat>(format);
Craig Donner6ebc46a2016-10-21 15:23:44 -0700119 info.layerCount = layerCount;
Craig Donnere96a3252017-02-02 12:13:34 -0800120 info.producerUsageMask = producerUsage;
121 info.consumerUsageMask = consumerUsage;
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800122
123 Gralloc2::BufferDescriptor descriptor;
Chia-I Wu67e376d2016-12-19 11:36:22 +0800124 auto error = mAllocator->createBufferDescriptor(info, &descriptor);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800125 if (error != Gralloc2::Error::NONE) {
Craig Donnere96a3252017-02-02 12:13:34 -0800126 ALOGE("Failed to create desc (%u x %u) layerCount %u format %d producerUsage %" PRIx64
127 " consumerUsage %" PRIx64 ": %d",
128 width, height, layerCount, format, producerUsage,
129 consumerUsage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800130 return;
131 }
132
Chia-I Wu67e376d2016-12-19 11:36:22 +0800133 error = mAllocator->allocate(descriptor, &mBuffer);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800134 if (error == Gralloc2::Error::NOT_SHARED) {
135 error = Gralloc2::Error::NONE;
136 }
137
138 if (error != Gralloc2::Error::NONE) {
Craig Donnere96a3252017-02-02 12:13:34 -0800139 ALOGE("Failed to allocate (%u x %u) layerCount %u format %d producerUsage %" PRIx64
140 " consumerUsage %" PRIx64 ": %d",
141 width, height, layerCount, format, producerUsage,
142 consumerUsage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800143 mAllocator->destroyBufferDescriptor(descriptor);
144 return;
145 }
146
Chia-I Wu67e376d2016-12-19 11:36:22 +0800147 error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800148 if (error != Gralloc2::Error::NONE) {
149 ALOGE("Failed to export handle");
150 mAllocator->free(mBuffer);
151 mAllocator->destroyBufferDescriptor(descriptor);
152 return;
153 }
154
155 mAllocator->destroyBufferDescriptor(descriptor);
156
157 mBufferValid = true;
158 }
159
160 ~HalBuffer()
161 {
162 if (mBufferValid) {
163 if (mHandle) {
164 native_handle_close(mHandle);
165 native_handle_delete(mHandle);
166 }
167
168 mAllocator->free(mBuffer);
169 }
170 }
171
172 bool exportHandle(GraphicBufferMapper& mapper,
173 buffer_handle_t* handle, uint32_t* stride)
174 {
175 if (!mBufferValid) {
176 return false;
177 }
178
179 if (mapper.registerBuffer(mHandle)) {
180 return false;
181 }
182
183 *handle = mHandle;
184
Chia-I Wu67e376d2016-12-19 11:36:22 +0800185 auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800186 if (error != Gralloc2::Error::NONE) {
187 ALOGW("Failed to get stride from buffer: %d", error);
188 *stride = 0;
189 }
190
191 mHandle = nullptr;
192 mAllocator->free(mBuffer);
193 mBufferValid = false;
194
195 return true;
196 }
197
198private:
199 const Gralloc2::Allocator* mAllocator;
200
201 bool mBufferValid;
202 Gralloc2::Buffer mBuffer;
203 native_handle_t* mHandle;
204};
205
206} // namespace
207
Dan Stoza8deb4da2016-06-01 18:21:44 -0700208status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
Craig Donnere96a3252017-02-02 12:13:34 -0800209 PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
210 uint64_t consumerUsage, buffer_handle_t* handle, uint32_t* stride,
211 uint64_t graphicBufferId, std::string requestorName)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700212{
Mathias Agopiancf563192012-02-29 20:43:29 -0800213 ATRACE_CALL();
Dan Stozad3182402014-11-17 12:03:59 -0800214
Mathias Agopian5629eb12010-04-15 14:57:39 -0700215 // make sure to not allocate a N x 0 or 0 x N buffer, since this is
216 // allowed from an API stand-point allocate a 1x1 buffer instead.
Dan Stozad3182402014-11-17 12:03:59 -0800217 if (!width || !height)
218 width = height = 1;
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700219
Craig Donner6ebc46a2016-10-21 15:23:44 -0700220 // Ensure that layerCount is valid.
221 if (layerCount < 1)
222 layerCount = 1;
223
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800224 gralloc1_error_t error;
225 if (mAllocator->valid()) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700226 HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
Craig Donnere96a3252017-02-02 12:13:34 -0800227 producerUsage, consumerUsage);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800228 if (!buffer.exportHandle(mMapper, handle, stride)) {
229 return NO_MEMORY;
230 }
231 error = GRALLOC1_ERROR_NONE;
232 } else {
233 auto descriptor = mDevice->createDescriptor();
234 error = descriptor->setDimensions(width, height);
235 if (error != GRALLOC1_ERROR_NONE) {
236 ALOGE("Failed to set dimensions to (%u, %u): %d",
237 width, height, error);
238 return BAD_VALUE;
239 }
240 error = descriptor->setFormat(
241 static_cast<android_pixel_format_t>(format));
242 if (error != GRALLOC1_ERROR_NONE) {
243 ALOGE("Failed to set format to %d: %d", format, error);
244 return BAD_VALUE;
245 }
Craig Donner6ebc46a2016-10-21 15:23:44 -0700246 if (mDevice->hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) {
247 error = descriptor->setLayerCount(layerCount);
248 if (error != GRALLOC1_ERROR_NONE) {
249 ALOGE("Failed to set layer count to %u: %d", layerCount, error);
250 return BAD_VALUE;
251 }
252 } else if (layerCount > 1) {
253 ALOGE("Failed to set layer count to %u: capability unsupported",
254 layerCount);
255 return BAD_VALUE;
256 }
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800257 error = descriptor->setProducerUsage(
Craig Donnere96a3252017-02-02 12:13:34 -0800258 static_cast<gralloc1_producer_usage_t>(producerUsage));
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800259 if (error != GRALLOC1_ERROR_NONE) {
Craig Donnere96a3252017-02-02 12:13:34 -0800260 ALOGE("Failed to set producer usage to %" PRIx64 ": %d",
261 producerUsage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800262 return BAD_VALUE;
263 }
264 error = descriptor->setConsumerUsage(
Craig Donnere96a3252017-02-02 12:13:34 -0800265 static_cast<gralloc1_consumer_usage_t>(consumerUsage));
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800266 if (error != GRALLOC1_ERROR_NONE) {
Craig Donnere96a3252017-02-02 12:13:34 -0800267 ALOGE("Failed to set consumer usage to %" PRIx64 ": %d",
268 consumerUsage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800269 return BAD_VALUE;
270 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700271
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800272 error = mDevice->allocate(descriptor, graphicBufferId, handle);
273 if (error != GRALLOC1_ERROR_NONE) {
Craig Donnere96a3252017-02-02 12:13:34 -0800274 ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
275 "producerUsage %" PRIx64 " consumerUsage %" PRIx64 ": %d",
276 width, height, layerCount, format, producerUsage,
277 consumerUsage, error);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800278 return NO_MEMORY;
279 }
Dan Stozad3182402014-11-17 12:03:59 -0800280
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800281 error = mDevice->getStride(*handle, stride);
282 if (error != GRALLOC1_ERROR_NONE) {
283 ALOGW("Failed to get stride from buffer: %d", error);
284 }
Dan Stoza8deb4da2016-06-01 18:21:44 -0700285 }
286
287 if (error == NO_ERROR) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700288 Mutex::Autolock _l(sLock);
289 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
Dan Stozad3182402014-11-17 12:03:59 -0800290 uint32_t bpp = bytesPerPixel(format);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700291 alloc_rec_t rec;
Dan Stozad3182402014-11-17 12:03:59 -0800292 rec.width = width;
293 rec.height = height;
294 rec.stride = *stride;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700295 rec.format = format;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700296 rec.layerCount = layerCount;
Craig Donnere96a3252017-02-02 12:13:34 -0800297 rec.producerUsage = producerUsage;
298 rec.consumerUsage = consumerUsage;
Dan Stozad3182402014-11-17 12:03:59 -0800299 rec.size = static_cast<size_t>(height * (*stride) * bpp);
Dan Stoza024e9312016-08-24 12:17:29 -0700300 rec.requestorName = std::move(requestorName);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700301 list.add(*handle, rec);
302 }
303
Dan Stoza8deb4da2016-06-01 18:21:44 -0700304 return NO_ERROR;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700305}
306
Mathias Agopian3330b202009-10-05 17:07:12 -0700307status_t GraphicBufferAllocator::free(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700308{
Mathias Agopiancf563192012-02-29 20:43:29 -0800309 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -0800310
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800311 gralloc1_error_t error;
312 if (mAllocator->valid()) {
313 error = static_cast<gralloc1_error_t>(
314 mMapper.unregisterBuffer(handle));
315 } else {
316 error = mDevice->release(handle);
317 }
318
Dan Stoza8deb4da2016-06-01 18:21:44 -0700319 if (error != GRALLOC1_ERROR_NONE) {
320 ALOGE("Failed to free buffer: %d", error);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700321 }
322
Dan Stoza8deb4da2016-06-01 18:21:44 -0700323 Mutex::Autolock _l(sLock);
324 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
325 list.removeItem(handle);
326
327 return NO_ERROR;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700328}
329
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700330// ---------------------------------------------------------------------------
331}; // namespace android