blob: 1ab70ec93978563728ded69ea531dc36a3d4f5a3 [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>
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070020#include <unistd.h>
Mathias Agopiana8a75162009-04-10 14:24:31 -070021
22#include <sys/mman.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25
26#include <cutils/log.h>
27#include <cutils/atomic.h>
28
29#include <hardware/hardware.h>
30#include <hardware/gralloc.h>
31
32#include "gralloc_priv.h"
33
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070034
35// we need this for now because pmem cannot mmap at an offset
36#define PMEM_HACK 1
37
Mathias Agopiana8a75162009-04-10 14:24:31 -070038/*****************************************************************************/
39
Mathias Agopian51156652009-06-09 18:55:49 -070040static int gralloc_map(gralloc_module_t const* module,
Mathias Agopiana8a75162009-04-10 14:24:31 -070041 buffer_handle_t handle,
42 void** vaddr)
43{
Mathias Agopian51156652009-06-09 18:55:49 -070044 private_handle_t* hnd = (private_handle_t*)handle;
45 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070046 size_t size = hnd->size;
47#if PMEM_HACK
48 size += hnd->offset;
49#endif
50 void* mappedAddress = mmap(0, size,
51 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
Mathias Agopian51156652009-06-09 18:55:49 -070052 if (mappedAddress == MAP_FAILED) {
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070053 LOGE("Could not mmap %s", strerror(errno));
Mathias Agopian51156652009-06-09 18:55:49 -070054 return -errno;
55 }
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070056 hnd->base = intptr_t(mappedAddress) + hnd->offset;
57 //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
58 // hnd->fd, hnd->offset, hnd->size, mappedAddress);
Mathias Agopiana8a75162009-04-10 14:24:31 -070059 }
Mathias Agopian51156652009-06-09 18:55:49 -070060 *vaddr = (void*)hnd->base;
61 return 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070062}
63
Mathias Agopian51156652009-06-09 18:55:49 -070064static int gralloc_unmap(gralloc_module_t const* module,
Mathias Agopiana8a75162009-04-10 14:24:31 -070065 buffer_handle_t handle)
66{
Mathias Agopian51156652009-06-09 18:55:49 -070067 private_handle_t* hnd = (private_handle_t*)handle;
68 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
69 if (munmap((void*)hnd->base, hnd->size) < 0) {
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070070 LOGE("Could not unmap %s", strerror(errno));
Mathias Agopian51156652009-06-09 18:55:49 -070071 }
Mathias Agopiana8a75162009-04-10 14:24:31 -070072 }
Mathias Agopian51156652009-06-09 18:55:49 -070073 hnd->base = 0;
74 return 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070075}
76
Mathias Agopian51156652009-06-09 18:55:49 -070077/*****************************************************************************/
78
79static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
80
81/*****************************************************************************/
82
Mathias Agopian988b8bd2009-05-04 14:26:56 -070083int gralloc_register_buffer(gralloc_module_t const* module,
84 buffer_handle_t handle)
85{
86 if (private_handle_t::validate(handle) < 0)
87 return -EINVAL;
Mathias Agopian51156652009-06-09 18:55:49 -070088
Mathias Agopian988b8bd2009-05-04 14:26:56 -070089 // In this implementation, we don't need to do anything here
90
Mathias Agopian51156652009-06-09 18:55:49 -070091 /* NOTE: we need to initialize the buffer as not mapped/not locked
Mathias Agopian988b8bd2009-05-04 14:26:56 -070092 * because it shouldn't when this function is called the first time
Mathias Agopian51156652009-06-09 18:55:49 -070093 * in a new process. Ideally these flags shouldn't be part of the
Mathias Agopian988b8bd2009-05-04 14:26:56 -070094 * handle, but instead maintained in the kernel or at least
95 * out-of-line
96 */
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070097
98 // if this handle was created in this process, then we keep it as is.
Mathias Agopian51156652009-06-09 18:55:49 -070099 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -0700100 if (hnd->pid != getpid()) {
101 hnd->base = 0;
102 hnd->lockState = 0;
103 hnd->writeOwner = 0;
104 }
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700105 return 0;
106}
107
108int gralloc_unregister_buffer(gralloc_module_t const* module,
109 buffer_handle_t handle)
110{
111 if (private_handle_t::validate(handle) < 0)
112 return -EINVAL;
113
114 /*
115 * If the buffer has been mapped during a lock operation, it's time
Mathias Agopian51156652009-06-09 18:55:49 -0700116 * to un-map it. It's an error to be here with a locked buffer.
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700117 * NOTE: the framebuffer is handled differently and is never unmapped.
118 */
119
Mathias Agopian51156652009-06-09 18:55:49 -0700120 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700121
Mathias Agopian51156652009-06-09 18:55:49 -0700122 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
123 "handle %p still locked (state=%08x)",
Mathias Agopian485e6982009-05-05 20:21:57 -0700124 hnd, hnd->lockState);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700125
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -0700126 // never unmap buffers that were created in this process
127 if (hnd->pid != getpid()) {
128 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
129 gralloc_unmap(module, handle);
130 }
131 hnd->base = 0;
132 hnd->lockState = 0;
133 hnd->writeOwner = 0;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700134 }
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700135 return 0;
136}
Mathias Agopiana8a75162009-04-10 14:24:31 -0700137
138int gralloc_lock(gralloc_module_t const* module,
139 buffer_handle_t handle, int usage,
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700140 int l, int t, int w, int h,
141 void** vaddr)
Mathias Agopiana8a75162009-04-10 14:24:31 -0700142{
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700143 if (private_handle_t::validate(handle) < 0)
144 return -EINVAL;
145
146 int err = 0;
Mathias Agopian51156652009-06-09 18:55:49 -0700147 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian485e6982009-05-05 20:21:57 -0700148 int32_t current_value, new_value;
149 int retry;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700150
Mathias Agopian485e6982009-05-05 20:21:57 -0700151 do {
152 current_value = hnd->lockState;
153 new_value = current_value;
Mathias Agopian51156652009-06-09 18:55:49 -0700154
155 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700156 // already locked for write
157 LOGE("handle %p already locked for write", handle);
158 return -EBUSY;
Mathias Agopian51156652009-06-09 18:55:49 -0700159 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700160 // already locked for read
161 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
162 LOGE("handle %p already locked for read", handle);
163 return -EBUSY;
164 } else {
Mathias Agopian82f7c042009-06-03 19:03:26 -0700165 // this is not an error
166 //LOGD("%p already locked for read... count = %d",
167 // handle, (current_value & ~(1<<31)));
Mathias Agopian485e6982009-05-05 20:21:57 -0700168 }
169 }
170
171 // not currently locked
172 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
173 // locking for write
Mathias Agopian51156652009-06-09 18:55:49 -0700174 new_value |= private_handle_t::LOCK_STATE_WRITE;
Mathias Agopian485e6982009-05-05 20:21:57 -0700175 }
176 new_value++;
177
178 retry = android_atomic_cmpxchg(current_value, new_value,
179 (volatile int32_t*)&hnd->lockState);
180 } while (retry);
Mathias Agopian51156652009-06-09 18:55:49 -0700181
182 if (new_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700183 // locking for write, store the tid
184 hnd->writeOwner = gettid();
185 }
186
187 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
Mathias Agopian51156652009-06-09 18:55:49 -0700188 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
189 // we need to map for real
190 pthread_mutex_t* const lock = &sMapLock;
191 pthread_mutex_lock(lock);
192 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
193 err = gralloc_map(module, handle, vaddr);
194 if (err == 0) {
195 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
196 (volatile int32_t*)&(hnd->lockState));
197 }
198 }
199 pthread_mutex_unlock(lock);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700200 }
Mathias Agopian51156652009-06-09 18:55:49 -0700201 *vaddr = (void*)hnd->base;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700202 }
Mathias Agopian485e6982009-05-05 20:21:57 -0700203
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700204 return err;
Mathias Agopiana8a75162009-04-10 14:24:31 -0700205}
206
207int gralloc_unlock(gralloc_module_t const* module,
208 buffer_handle_t handle)
209{
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700210 if (private_handle_t::validate(handle) < 0)
211 return -EINVAL;
212
Mathias Agopian51156652009-06-09 18:55:49 -0700213 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian485e6982009-05-05 20:21:57 -0700214 int32_t current_value, new_value;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700215
Mathias Agopian485e6982009-05-05 20:21:57 -0700216 do {
217 current_value = hnd->lockState;
218 new_value = current_value;
219
Mathias Agopian51156652009-06-09 18:55:49 -0700220 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700221 // locked for write
222 if (hnd->writeOwner == gettid()) {
223 hnd->writeOwner = 0;
Mathias Agopian51156652009-06-09 18:55:49 -0700224 new_value &= ~private_handle_t::LOCK_STATE_WRITE;
Mathias Agopian485e6982009-05-05 20:21:57 -0700225 }
226 }
227
Mathias Agopian51156652009-06-09 18:55:49 -0700228 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700229 LOGE("handle %p not locked", handle);
230 return -EINVAL;
231 }
232
233 new_value--;
234
235 } while (android_atomic_cmpxchg(current_value, new_value,
236 (volatile int32_t*)&hnd->lockState));
237
Mathias Agopiana8a75162009-04-10 14:24:31 -0700238 return 0;
239}