1/* 2** 3** Copyright 2009, The Android Open Source Project 4** 5** 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 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** 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 15** limitations under the License. 16*/ 17 18#define LOG_TAG "GraphicBufferAllocator" 19#define ATRACE_TAG ATRACE_TAG_GRAPHICS 20 21#include <ui/GraphicBufferAllocator.h> 22 23#include <stdio.h> 24 25#include <grallocusage/GrallocUsageConversion.h> 26 27#include <log/log.h> 28#include <utils/Singleton.h> 29#include <utils/String8.h> 30#include <utils/Trace.h> 31 32#include <ui/Gralloc2.h> 33#include <ui/GraphicBufferMapper.h> 34 35namespace android { 36// --------------------------------------------------------------------------- 37 38ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator ) 39 40Mutex GraphicBufferAllocator::sLock; 41KeyedVector<buffer_handle_t, 42 GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList; 43 44GraphicBufferAllocator::GraphicBufferAllocator() 45 : mMapper(GraphicBufferMapper::getInstance()), 46 mAllocator(std::make_unique<Gralloc2::Allocator>( 47 mMapper.getGrallocMapper())) 48{ 49} 50 51GraphicBufferAllocator::~GraphicBufferAllocator() {} 52 53void GraphicBufferAllocator::dump(String8& result) const 54{ 55 Mutex::Autolock _l(sLock); 56 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); 57 size_t total = 0; 58 const size_t SIZE = 4096; 59 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)); 65 if (rec.size) { 66 snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 67 " | %s\n", 68 list.keyAt(i), rec.size/1024.0, 69 rec.width, rec.stride, rec.height, rec.layerCount, rec.format, 70 rec.usage, rec.requestorName.c_str()); 71 } else { 72 snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 73 " | %s\n", 74 list.keyAt(i), 75 rec.width, rec.stride, rec.height, rec.layerCount, rec.format, 76 rec.usage, rec.requestorName.c_str()); 77 } 78 result.append(buffer); 79 total += rec.size; 80 } 81 snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0); 82 result.append(buffer); 83 84 std::string deviceDump = mAllocator->dumpDebugInfo(); 85 result.append(deviceDump.c_str(), deviceDump.size()); 86} 87 88void GraphicBufferAllocator::dumpToSystemLog() 89{ 90 String8 s; 91 GraphicBufferAllocator::getInstance().dump(s); 92 ALOGD("%s", s.string()); 93} 94 95status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, 96 PixelFormat format, uint32_t layerCount, uint64_t usage, 97 buffer_handle_t* handle, uint32_t* stride, 98 uint64_t /*graphicBufferId*/, std::string requestorName) 99{ 100 ATRACE_CALL(); 101 102 // make sure to not allocate a N x 0 or 0 x N buffer, since this is 103 // allowed from an API stand-point allocate a 1x1 buffer instead. 104 if (!width || !height) 105 width = height = 1; 106 107 // Ensure that layerCount is valid. 108 if (layerCount < 1) 109 layerCount = 1; 110 111 Gralloc2::IMapper::BufferDescriptorInfo info = {}; 112 info.width = width; 113 info.height = height; 114 info.layerCount = layerCount; 115 info.format = static_cast<Gralloc2::PixelFormat>(format); 116 info.usage = usage; 117 118 Gralloc2::Error error = mAllocator->allocate(info, stride, handle); 119 if (error == Gralloc2::Error::NONE) { 120 Mutex::Autolock _l(sLock); 121 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); 122 uint32_t bpp = bytesPerPixel(format); 123 alloc_rec_t rec; 124 rec.width = width; 125 rec.height = height; 126 rec.stride = *stride; 127 rec.format = format; 128 rec.layerCount = layerCount; 129 rec.usage = usage; 130 rec.size = static_cast<size_t>(height * (*stride) * bpp); 131 rec.requestorName = std::move(requestorName); 132 list.add(*handle, rec); 133 134 return NO_ERROR; 135 } else { 136 ALOGE("Failed to allocate (%u x %u) layerCount %u format %d " 137 "usage %" PRIx64 ": %d", 138 width, height, layerCount, format, usage, 139 error); 140 return NO_MEMORY; 141 } 142} 143 144status_t GraphicBufferAllocator::free(buffer_handle_t handle) 145{ 146 ATRACE_CALL(); 147 148 // We allocated a buffer from the allocator and imported it into the 149 // mapper to get the handle. We just need to free the handle now. 150 mMapper.freeBuffer(handle); 151 152 Mutex::Autolock _l(sLock); 153 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); 154 list.removeItem(handle); 155 156 return NO_ERROR; 157} 158 159// --------------------------------------------------------------------------- 160}; // namespace android 161