blob: a5f52ede8ce86bb51652de86a8dfa918de928d1f [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
41 int init(private_handle_t* hnd) {
42 size = hnd->size;
43 base = 0;
44 refCount = 0;
45 struct stat buf;
46 int result = 0;
47 key = intptr_t(hnd);
48 return result;
49 }
50};
51
52static int compare(const mapped_buffer_t& a, const mapped_buffer_t& b) {
53 if (a.key < b.key) {
54 return -1;
55 }
56 if (a.key > b.key) {
57 return 1;
58 }
59 return 0;
60}
61
62struct mapped_buffers_t {
63 pthread_mutex_t mutex;
64 growable_sorted_array_t<mapped_buffer_t> records;
65
66 int map(gralloc_module_t const* module,
67 buffer_handle_t handle,
68 void** vaddr)
69 {
70 private_handle_t* hnd = (private_handle_t*)(handle);
71 mapped_buffer_t key;
72 int result = key.init(hnd);
73 //printRecord(ANDROID_LOG_DEBUG, "map", &key);
74 if (result) {
75 return result;
76 }
77 mapped_buffer_t* record = 0;
78 pthread_mutex_lock(&mutex);
79 // From here to the end of the function we return by jumping to "exit"
80 // so that we always unlock the mutex.
81
82 int index = -1;
83 if (!records.find(key, index)) {
84 //LOGD("New item at %d", index);
85 void* mappedAddress = mmap(0, hnd->size,
86 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
87 if (mappedAddress == MAP_FAILED) {
88 result = -errno;
89 //LOGE("map failed %d", result);
90 goto exit;
91 }
92 key.base = intptr_t(mappedAddress);
93 records.insert(index, key);
94 record = records.at(index);
95 } else {
96 //LOGD("Found existing mapping at index %d", index);
97 record = records.at(index);
98 if (record->size != key.size) {
99 LOGE("Requested a new mapping at the same offset"
100 "but with a different size");
101 printRecord(ANDROID_LOG_ERROR, "old", record);
102 printRecord(ANDROID_LOG_ERROR, "new", &key);
103 result = -EINVAL;
104 goto exit;
105 }
106 }
107 record->refCount += 1;
108 hnd->base = record->base;
109 *vaddr = (void*) record->base;
110 exit:
111 //print();
112 pthread_mutex_unlock(&mutex);
113 return result;
114 }
115
116 int unmap(gralloc_module_t const* module,
117 buffer_handle_t handle)
118 {
119 mapped_buffer_t key;
120 key.init((private_handle_t*) handle);
121 //printRecord(ANDROID_LOG_DEBUG, "unmap", &key);
122 int index = -1;
123
124 int result = 0;
125 mapped_buffer_t* record = 0;
126 pthread_mutex_lock(&mutex);
127 // From here to the end of the function we return by jumping to "exit"
128 // so that we always unlock the mutex.
129
130 if (!records.find(key, index)) {
131 // This handle is not currently locked.
132 //LOGE("Could not find existing mapping near %d", index);
133 result = -ENOENT;
134 goto exit;
135 }
136 record = records.at(index);
137 //printRecord(ANDROID_LOG_DEBUG, "record", record);
138 record->refCount -= 1;
139 if (record->refCount == 0) {
140 //LOGD("Unmapping...");
141 if (munmap((void*)record->base, record->size) < 0) {
142 result = -errno;
143 //LOGE("Could not unmap %d", result);
144 }
145 records.remove(index);
146 ((private_handle_t*)handle)->base = 0;
147 }
148
149 exit:
150 //print();
151 pthread_mutex_unlock(&mutex);
152 return result;
153 }
154
155 void print() {
156 char prefix[16];
157 LOGD("Dumping records: count=%d size=%d", records.count, records.size);
158 for(int i=0; i<records.count ; i++) {
159 sprintf(prefix, "%3d", i);
160 printRecord(ANDROID_LOG_DEBUG, prefix, records.at(i));
161 }
162 }
163
164 void printRecord(int level, const char* what, mapped_buffer_t* record) {
165 LOG_PRI(level, LOG_TAG,
166 "%s: key=0x%08x, size=0x%08x, base=0x%08x refCount=%d",
167 what, int(record->key), record->size,
168 record->base, record->refCount);
169 }
170};
171
172static mapped_buffers_t sMappedBuffers = {
173 mutex: PTHREAD_MUTEX_INITIALIZER
174};
175
176/*****************************************************************************/
177
178int gralloc_map(gralloc_module_t const* module,
179 buffer_handle_t handle,
180 void** vaddr)
181{
182 if (private_handle_t::validate(handle) < 0)
183 return -EINVAL;
184
185 private_handle_t* hnd = (private_handle_t*)(handle);
186 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
187 const private_module_t* m =
188 reinterpret_cast<const private_module_t*>(module);
189 handle = m->framebuffer;
190 }
191
192 int err = sMappedBuffers.map(module, handle, vaddr);
193
194 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
195 *vaddr = (void*)hnd->base;
196 }
197
198 return err;
199}
200
201int gralloc_unmap(gralloc_module_t const* module,
202 buffer_handle_t handle)
203{
204 if (private_handle_t::validate(handle) < 0)
205 return -EINVAL;
206
207 private_handle_t* hnd = (private_handle_t*)(handle);
208 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
209 const private_module_t* m =
210 reinterpret_cast<const private_module_t*>(module);
211 handle = m->framebuffer;
212 }
213
214 return sMappedBuffers.unmap(module, handle);
215}
216
217
218int gralloc_lock(gralloc_module_t const* module,
219 buffer_handle_t handle, int usage,
220 int l, int t, int w, int h)
221{
222 // FIXME: gralloc_lock() needs implementation
223 return 0;
224}
225
226int gralloc_unlock(gralloc_module_t const* module,
227 buffer_handle_t handle)
228{
229 // FIXME: gralloc_unlock() needs implementation
230 return 0;
231}