blob: fec7c8770584feafb7590306206e6f8c2406571b [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 Agopian9f88afb2009-04-17 14:15:18 -070037ANDROID_SINGLETON_STATIC_INSTANCE( BufferAllocator )
Mathias Agopian4243e662009-04-15 18:34:24 -070038
Mathias Agopian076b1cc2009-04-10 14:24:30 -070039Mutex BufferAllocator::sLock;
40KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList;
41
42BufferAllocator::BufferAllocator()
43 : mAllocDev(0)
44{
45 hw_module_t const* module;
46 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
47 LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
48 if (err == 0) {
49 gralloc_open(module, &mAllocDev);
50 }
51}
52
53BufferAllocator::~BufferAllocator()
54{
55 gralloc_close(mAllocDev);
56}
57
58void BufferAllocator::dump(String8& result) const
59{
60 Mutex::Autolock _l(sLock);
61 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
62 size_t total = 0;
63 const size_t SIZE = 512;
64 char buffer[SIZE];
65 snprintf(buffer, SIZE, "Allocated buffers:\n");
66 result.append(buffer);
67 const size_t c = list.size();
68 for (size_t i=0 ; i<c ; i++) {
69 const alloc_rec_t& rec(list.valueAt(i));
70 snprintf(buffer, SIZE, "%10p: %10p | %7.2f KB | %4u x %4u | %2d | 0x%08x\n",
71 list.keyAt(i), rec.vaddr, rec.size/1024.0f,
72 rec.w, rec.h, rec.format, rec.usage);
73 result.append(buffer);
74 total += rec.size;
75 }
76 snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f);
77 result.append(buffer);
78}
79
80status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
81 int usage, buffer_handle_t* handle, int32_t* stride)
82{
83 Mutex::Autolock _l(mLock);
84
85 // we have a h/w allocator and h/w buffer is requested
86 status_t err = mAllocDev->alloc(mAllocDev,
87 w, h, format, usage, handle, stride);
88 LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
89 w, h, format, usage, err, strerror(-err));
90
91 if (err == NO_ERROR) {
92 Mutex::Autolock _l(sLock);
93 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
94 alloc_rec_t rec;
95 rec.w = w;
96 rec.h = h;
97 rec.format = format;
98 rec.usage = usage;
99 rec.vaddr = 0;
100 rec.size = h * stride[0] * bytesPerPixel(format);
101 list.add(*handle, rec);
102 }
103
104 return err;
105}
106
107status_t BufferAllocator::free(buffer_handle_t handle)
108{
109 Mutex::Autolock _l(mLock);
110
Mathias Agopian8b765b72009-04-10 20:34:46 -0700111#if ANDROID_GRALLOC_DEBUG
112 void* base = (void*)(handle->data[2]);
Mathias Agopian4243e662009-04-15 18:34:24 -0700113#endif
114
115 status_t err = mAllocDev->free(mAllocDev, handle);
116 LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
117
118#if ANDROID_GRALLOC_DEBUG
Mathias Agopian8b765b72009-04-10 20:34:46 -0700119 if (base) {
Mathias Agopian4243e662009-04-15 18:34:24 -0700120 LOGD("freeing mapped handle %p from:", handle);
Mathias Agopian8b765b72009-04-10 20:34:46 -0700121 CallStack s;
122 s.update();
123 s.dump("");
124 BufferMapper::get().dump(handle);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700125 }
126#endif
127
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700128 if (err == NO_ERROR) {
129 Mutex::Autolock _l(sLock);
130 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
131 list.removeItem(handle);
132 }
133
134 return err;
135}
136
137status_t BufferAllocator::map(buffer_handle_t handle, void** addr)
138{
139 Mutex::Autolock _l(mLock);
Mathias Agopian4243e662009-04-15 18:34:24 -0700140 status_t err = BufferMapper::get().map(handle, addr, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700141 if (err == NO_ERROR) {
142 Mutex::Autolock _l(sLock);
143 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
144 ssize_t idx = list.indexOfKey(handle);
145 if (idx >= 0)
146 list.editValueAt(idx).vaddr = addr;
147 }
148
149 return err;
150}
151
152status_t BufferAllocator::unmap(buffer_handle_t handle)
153{
154 Mutex::Autolock _l(mLock);
155 gralloc_module_t* mod = (gralloc_module_t*)mAllocDev->common.module;
Mathias Agopian4243e662009-04-15 18:34:24 -0700156 status_t err = BufferMapper::get().unmap(handle, this);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700157 if (err == NO_ERROR) {
158 Mutex::Autolock _l(sLock);
159 KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
160 ssize_t idx = list.indexOfKey(handle);
161 if (idx >= 0)
162 list.editValueAt(idx).vaddr = 0;
163 }
164
165 return err;
166}
167
168
169// ---------------------------------------------------------------------------
170}; // namespace android