blob: 94be43bdd13068771d68091da2a8f76b41314295 [file] [log] [blame]
Mathias Agopiana8a75162009-04-10 14:24:31 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <limits.h>
18#include <errno.h>
19#include <pthread.h>
20
21#include <sys/mman.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24
25#include <cutils/log.h>
26#include <cutils/atomic.h>
27
28#include <hardware/hardware.h>
29#include <hardware/gralloc.h>
30
31#include "gralloc_priv.h"
32
33/*****************************************************************************/
34
35struct mapped_buffer_t {
36 intptr_t key;
37 int size;
38 int base;
39 int refCount;
40
Mathias Agopian988b8bd2009-05-04 14:26:56 -070041 mapped_buffer_t() { /* no init */ };
42 mapped_buffer_t(private_handle_t* hnd)
43 : key(intptr_t(hnd)), size(hnd->size), base(0), refCount(0) {
Mathias Agopiana8a75162009-04-10 14:24:31 -070044 }
45};
46
47static int compare(const mapped_buffer_t& a, const mapped_buffer_t& b) {
48 if (a.key < b.key) {
49 return -1;
50 }
51 if (a.key > b.key) {
52 return 1;
53 }
54 return 0;
55}
56
57struct mapped_buffers_t {
58 pthread_mutex_t mutex;
59 growable_sorted_array_t<mapped_buffer_t> records;
60
61 int map(gralloc_module_t const* module,
62 buffer_handle_t handle,
63 void** vaddr)
64 {
65 private_handle_t* hnd = (private_handle_t*)(handle);
Mathias Agopian988b8bd2009-05-04 14:26:56 -070066 mapped_buffer_t key(hnd);
Mathias Agopiana8a75162009-04-10 14:24:31 -070067 //printRecord(ANDROID_LOG_DEBUG, "map", &key);
Mathias Agopian988b8bd2009-05-04 14:26:56 -070068 int result = 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070069 mapped_buffer_t* record = 0;
70 pthread_mutex_lock(&mutex);
71 // From here to the end of the function we return by jumping to "exit"
72 // so that we always unlock the mutex.
73
74 int index = -1;
75 if (!records.find(key, index)) {
76 //LOGD("New item at %d", index);
77 void* mappedAddress = mmap(0, hnd->size,
78 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
79 if (mappedAddress == MAP_FAILED) {
80 result = -errno;
81 //LOGE("map failed %d", result);
82 goto exit;
83 }
84 key.base = intptr_t(mappedAddress);
85 records.insert(index, key);
86 record = records.at(index);
87 } else {
88 //LOGD("Found existing mapping at index %d", index);
89 record = records.at(index);
90 if (record->size != key.size) {
91 LOGE("Requested a new mapping at the same offset"
92 "but with a different size");
93 printRecord(ANDROID_LOG_ERROR, "old", record);
94 printRecord(ANDROID_LOG_ERROR, "new", &key);
95 result = -EINVAL;
96 goto exit;
97 }
98 }
99 record->refCount += 1;
100 hnd->base = record->base;
101 *vaddr = (void*) record->base;
102 exit:
103 //print();
104 pthread_mutex_unlock(&mutex);
105 return result;
106 }
107
108 int unmap(gralloc_module_t const* module,
109 buffer_handle_t handle)
110 {
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700111 mapped_buffer_t key((private_handle_t*) handle);
Mathias Agopiana8a75162009-04-10 14:24:31 -0700112 //printRecord(ANDROID_LOG_DEBUG, "unmap", &key);
113 int index = -1;
Mathias Agopiana8a75162009-04-10 14:24:31 -0700114 int result = 0;
115 mapped_buffer_t* record = 0;
116 pthread_mutex_lock(&mutex);
117 // From here to the end of the function we return by jumping to "exit"
118 // so that we always unlock the mutex.
119
120 if (!records.find(key, index)) {
121 // This handle is not currently locked.
122 //LOGE("Could not find existing mapping near %d", index);
123 result = -ENOENT;
124 goto exit;
125 }
126 record = records.at(index);
127 //printRecord(ANDROID_LOG_DEBUG, "record", record);
128 record->refCount -= 1;
129 if (record->refCount == 0) {
130 //LOGD("Unmapping...");
131 if (munmap((void*)record->base, record->size) < 0) {
132 result = -errno;
133 //LOGE("Could not unmap %d", result);
134 }
135 records.remove(index);
136 ((private_handle_t*)handle)->base = 0;
137 }
138
139 exit:
140 //print();
141 pthread_mutex_unlock(&mutex);
142 return result;
143 }
144
145 void print() {
146 char prefix[16];
147 LOGD("Dumping records: count=%d size=%d", records.count, records.size);
148 for(int i=0; i<records.count ; i++) {
149 sprintf(prefix, "%3d", i);
150 printRecord(ANDROID_LOG_DEBUG, prefix, records.at(i));
151 }
152 }
153
154 void printRecord(int level, const char* what, mapped_buffer_t* record) {
155 LOG_PRI(level, LOG_TAG,
156 "%s: key=0x%08x, size=0x%08x, base=0x%08x refCount=%d",
157 what, int(record->key), record->size,
158 record->base, record->refCount);
159 }
160};
161
162static mapped_buffers_t sMappedBuffers = {
163 mutex: PTHREAD_MUTEX_INITIALIZER
164};
165
166/*****************************************************************************/
167
168int gralloc_map(gralloc_module_t const* module,
169 buffer_handle_t handle,
170 void** vaddr)
171{
172 if (private_handle_t::validate(handle) < 0)
173 return -EINVAL;
174
175 private_handle_t* hnd = (private_handle_t*)(handle);
176 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
177 const private_module_t* m =
178 reinterpret_cast<const private_module_t*>(module);
179 handle = m->framebuffer;
180 }
181
182 int err = sMappedBuffers.map(module, handle, vaddr);
183
184 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
185 *vaddr = (void*)hnd->base;
186 }
187
188 return err;
189}
190
191int gralloc_unmap(gralloc_module_t const* module,
192 buffer_handle_t handle)
193{
194 if (private_handle_t::validate(handle) < 0)
195 return -EINVAL;
196
197 private_handle_t* hnd = (private_handle_t*)(handle);
198 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
199 const private_module_t* m =
200 reinterpret_cast<const private_module_t*>(module);
201 handle = m->framebuffer;
202 }
203
204 return sMappedBuffers.unmap(module, handle);
205}
206
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700207int gralloc_register_buffer(gralloc_module_t const* module,
208 buffer_handle_t handle)
209{
210 if (private_handle_t::validate(handle) < 0)
211 return -EINVAL;
212
213 // In this implementation, we don't need to do anything here
214
215 /* FIXME: we need to initialize the buffer as not mapped/not locked
216 * because it shouldn't when this function is called the first time
217 * in a new process. ideally these flags shouldn't be part of the
218 * handle, but instead maintained in the kernel or at least
219 * out-of-line
220 */
221 private_handle_t* hnd = (private_handle_t*)(handle);
222 hnd->base = 0;
223 hnd->flags &= ~(private_handle_t::PRIV_FLAGS_LOCKED |
224 private_handle_t::PRIV_FLAGS_MAPPED);
225
226 return 0;
227}
228
229int gralloc_unregister_buffer(gralloc_module_t const* module,
230 buffer_handle_t handle)
231{
232 if (private_handle_t::validate(handle) < 0)
233 return -EINVAL;
234
235 /*
236 * If the buffer has been mapped during a lock operation, it's time
237 * to unmap it. It's an error to be here with a locked buffer.
238 * NOTE: the framebuffer is handled differently and is never unmapped.
239 */
240
241 private_handle_t* hnd = (private_handle_t*)(handle);
242
243 LOGE_IF(hnd->flags & private_handle_t::PRIV_FLAGS_LOCKED,
244 "handle %p still locked", hnd);
245
246 if (hnd->flags & private_handle_t::PRIV_FLAGS_MAPPED) {
247 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
248 gralloc_unmap(module, handle);
249 LOGE_IF(hnd->base,
250 "handle %p still mapped at %p",
251 hnd, (void*)hnd->base);
252 }
253 }
254
255 return 0;
256}
Mathias Agopiana8a75162009-04-10 14:24:31 -0700257
258int gralloc_lock(gralloc_module_t const* module,
259 buffer_handle_t handle, int usage,
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700260 int l, int t, int w, int h,
261 void** vaddr)
Mathias Agopiana8a75162009-04-10 14:24:31 -0700262{
263 // FIXME: gralloc_lock() needs implementation
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700264
265 if (private_handle_t::validate(handle) < 0)
266 return -EINVAL;
267
268 int err = 0;
269 private_handle_t* hnd = (private_handle_t*)(handle);
270
271 // already locked
272 if (hnd->flags & private_handle_t::PRIV_FLAGS_LOCKED) {
273 LOGE("handle %p already locked", handle);
274 return -EBUSY;
275 }
276
277 uint32_t mask = GRALLOC_USAGE_SW_READ_MASK |
278 GRALLOC_USAGE_SW_WRITE_MASK;
279 if ((usage & mask) && vaddr){
280 if (hnd->flags & private_handle_t::PRIV_FLAGS_MAPPED) {
281 *vaddr = (void*)hnd->base;
282 } else {
283 hnd->flags |= private_handle_t::PRIV_FLAGS_MAPPED;
284 err = gralloc_map(module, handle, vaddr);
285 }
286 }
287
288 hnd->flags |= private_handle_t::PRIV_FLAGS_LOCKED;
289 return err;
Mathias Agopiana8a75162009-04-10 14:24:31 -0700290}
291
292int gralloc_unlock(gralloc_module_t const* module,
293 buffer_handle_t handle)
294{
295 // FIXME: gralloc_unlock() needs implementation
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700296 if (private_handle_t::validate(handle) < 0)
297 return -EINVAL;
298
299 private_handle_t* hnd = (private_handle_t*)(handle);
300
301 // not locked
302 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_LOCKED)) {
303 LOGE("handle %p is not locked", handle);
304 return -EINVAL;
305 }
306
307 /* FOR DEBUGGING
308 if (hnd->flags & private_handle_t::PRIV_FLAGS_MAPPED) {
309 if (gralloc_unmap(module, handle) == 0) {
310 hnd->flags &= ~private_handle_t::PRIV_FLAGS_MAPPED;
311 }
312 }
313 */
314
315 hnd->flags &= ~private_handle_t::PRIV_FLAGS_LOCKED;
Mathias Agopiana8a75162009-04-10 14:24:31 -0700316 return 0;
317}