blob: 28fe81002f9e51f7ddbec2038390365f109c9022 [file] [log] [blame]
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001/*
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#include <sys/mman.h>
19#include <utils/CallStack.h>
20#include <cutils/ashmem.h>
21#include <cutils/log.h>
Mathias Agopian4243e662009-04-15 18:34:24 -070022
23#include <utils/Singleton.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070024#include <utils/String8.h>
25
26#include <ui/BufferMapper.h>
27
28#include "BufferAllocator.h"
29
30// FIXME: ANDROID_GRALLOC_DEBUG must only be used with *our* gralloc
31#define ANDROID_GRALLOC_DEBUG 1
32
33
34namespace android {
35// ---------------------------------------------------------------------------
36
Mathias Agopian4243e662009-04-15 18:34:24 -070037template<class BufferAllocator> Mutex Singleton<BufferAllocator>::sLock;
38template<> BufferAllocator* Singleton<BufferAllocator>::sInstance(0);
39
Mathias Agopian076b1cc2009-04-10 14:24:30 -070040Mutex BufferAllocator::sLock;
41KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList;
42
43BufferAllocator::BufferAllocator()
44 : mAllocDev(0)
45{
46 hw_module_t const* module;
47 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
48 LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
49 if (err == 0) {
50 gralloc_open(module, &mAllocDev);
51 }
52}
53
54BufferAllocator::~BufferAllocator()
55{
56 gralloc_close(mAllocDev);
57}
58
59void BufferAllocator::dump(String8& result) const
60{
61 Mutex::Autolock _l(sLock);
62 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
63 size_t total = 0;
64 const size_t SIZE = 512;
65 char buffer[SIZE];
66 snprintf(buffer, SIZE, "Allocated buffers:\n");
67 result.append(buffer);
68 const size_t c = list.size();
69 for (size_t i=0 ; i<c ; i++) {
70 const alloc_rec_t& rec(list.valueAt(i));
71 snprintf(buffer, SIZE, "%10p: %10p | %7.2f KB | %4u x %4u | %2d | 0x%08x\n",
72 list.keyAt(i), rec.vaddr, rec.size/1024.0f,
73 rec.w, rec.h, rec.format, rec.usage);
74 result.append(buffer);
75 total += rec.size;
76 }
77 snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f);
78 result.append(buffer);
79}
80
81status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
82 int usage, buffer_handle_t* handle, int32_t* stride)
83{
84 Mutex::Autolock _l(mLock);
85
86 // we have a h/w allocator and h/w buffer is requested
87 status_t err = mAllocDev->alloc(mAllocDev,
88 w, h, format, usage, handle, stride);
89 LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
90 w, h, format, usage, err, strerror(-err));
91
92 if (err == NO_ERROR) {
93 Mutex::Autolock _l(sLock);
94 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
95 alloc_rec_t rec;
96 rec.w = w;
97 rec.h = h;
98 rec.format = format;
99 rec.usage = usage;
100 rec.vaddr = 0;
101 rec.size = h * stride[0] * bytesPerPixel(format);
102 list.add(*handle, rec);
103 }
104
105 return err;
106}
107
108status_t BufferAllocator::free(buffer_handle_t handle)
109{
110 Mutex::Autolock _l(mLock);
111
Mathias Agopian8b765b72009-04-10 20:34:46 -0700112#if ANDROID_GRALLOC_DEBUG
113 void* base = (void*)(handle->data[2]);
Mathias Agopian4243e662009-04-15 18:34:24 -0700114#endif
115
116 status_t err = mAllocDev->free(mAllocDev, handle);
117 LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
118
119#if ANDROID_GRALLOC_DEBUG
Mathias Agopian8b765b72009-04-10 20:34:46 -0700120 if (base) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700121 LOGD("freeing mapped handle %p from:", handle);
Mathias Agopian8b765b72009-04-10 20:34:46 -0700122 CallStack s;
123 s.update();
124 s.dump("");
125 BufferMapper::get().dump(handle);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700126 }
127#endif
128
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700129 if (err == NO_ERROR) {
130 Mutex::Autolock _l(sLock);
131 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
132 list.removeItem(handle);
133 }
134
135 return err;
136}
137
138status_t BufferAllocator::map(buffer_handle_t handle, void** addr)
139{
140 Mutex::Autolock _l(mLock);
Mathias Agopian4243e662009-04-15 18:34:24 -0700141 status_t err = BufferMapper::get().map(handle, addr, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700142 if (err == NO_ERROR) {
143 Mutex::Autolock _l(sLock);
144 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
145 ssize_t idx = list.indexOfKey(handle);
146 if (idx >= 0)
147 list.editValueAt(idx).vaddr = addr;
148 }
149
150 return err;
151}
152
153status_t BufferAllocator::unmap(buffer_handle_t handle)
154{
155 Mutex::Autolock _l(mLock);
156 gralloc_module_t* mod = (gralloc_module_t*)mAllocDev->common.module;
Mathias Agopian4243e662009-04-15 18:34:24 -0700157 status_t err = BufferMapper::get().unmap(handle, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700158 if (err == NO_ERROR) {
159 Mutex::Autolock _l(sLock);
160 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
161 ssize_t idx = list.indexOfKey(handle);
162 if (idx >= 0)
163 list.editValueAt(idx).vaddr = 0;
164 }
165
166 return err;
167}
168
169
170// ---------------------------------------------------------------------------
171}; // namespace android