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 35 namespace android { 36 // --------------------------------------------------------------------------- 37 38 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator ) 39 40 Mutex GraphicBufferAllocator::sLock; 41 KeyedVector<buffer_handle_t, 42 GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList; 43 44 GraphicBufferAllocator::GraphicBufferAllocator() 45 : mMapper(GraphicBufferMapper::getInstance()), 46 mAllocator(std::make_unique<Gralloc2::Allocator>( 47 mMapper.getGrallocMapper())) 48 { 49 } 50 51 GraphicBufferAllocator::~GraphicBufferAllocator() {} 52 53 void 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 88 void GraphicBufferAllocator::dumpToSystemLog() 89 { 90 String8 s; 91 GraphicBufferAllocator::getInstance().dump(s); 92 ALOGD("%s", s.string()); 93 } 94 95 status_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 144 status_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