blob: f13c315d2c6ae7abf423a1f1fa069d9e5858e845 [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
Mathias Agopian51156652009-06-09 18:55:49 -070035static int gralloc_map(gralloc_module_t const* module,
Mathias Agopiana8a75162009-04-10 14:24:31 -070036 buffer_handle_t handle,
37 void** vaddr)
38{
Mathias Agopian51156652009-06-09 18:55:49 -070039 private_handle_t* hnd = (private_handle_t*)handle;
40 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
41 void* mappedAddress = mmap(0, hnd->size, PROT_READ|PROT_WRITE,
42 MAP_SHARED, hnd->fd, 0);
43 if (mappedAddress == MAP_FAILED) {
44 return -errno;
45 }
46 hnd->base = intptr_t(mappedAddress);
Mathias Agopiana8a75162009-04-10 14:24:31 -070047 }
Mathias Agopian51156652009-06-09 18:55:49 -070048 *vaddr = (void*)hnd->base;
49 return 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070050}
51
Mathias Agopian51156652009-06-09 18:55:49 -070052static int gralloc_unmap(gralloc_module_t const* module,
Mathias Agopiana8a75162009-04-10 14:24:31 -070053 buffer_handle_t handle)
54{
Mathias Agopian51156652009-06-09 18:55:49 -070055 private_handle_t* hnd = (private_handle_t*)handle;
56 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
57 if (munmap((void*)hnd->base, hnd->size) < 0) {
58 LOGE("Could not unmap %d", errno);
59 }
Mathias Agopiana8a75162009-04-10 14:24:31 -070060 }
Mathias Agopian51156652009-06-09 18:55:49 -070061 hnd->base = 0;
62 return 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070063}
64
Mathias Agopian51156652009-06-09 18:55:49 -070065/*****************************************************************************/
66
67static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
68
69/*****************************************************************************/
70
Mathias Agopian988b8bd2009-05-04 14:26:56 -070071int gralloc_register_buffer(gralloc_module_t const* module,
72 buffer_handle_t handle)
73{
74 if (private_handle_t::validate(handle) < 0)
75 return -EINVAL;
Mathias Agopian51156652009-06-09 18:55:49 -070076
Mathias Agopian988b8bd2009-05-04 14:26:56 -070077 // In this implementation, we don't need to do anything here
78
Mathias Agopian51156652009-06-09 18:55:49 -070079 /* NOTE: we need to initialize the buffer as not mapped/not locked
Mathias Agopian988b8bd2009-05-04 14:26:56 -070080 * because it shouldn't when this function is called the first time
Mathias Agopian51156652009-06-09 18:55:49 -070081 * in a new process. Ideally these flags shouldn't be part of the
Mathias Agopian988b8bd2009-05-04 14:26:56 -070082 * handle, but instead maintained in the kernel or at least
83 * out-of-line
84 */
Mathias Agopian51156652009-06-09 18:55:49 -070085 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian988b8bd2009-05-04 14:26:56 -070086 hnd->base = 0;
Mathias Agopian51156652009-06-09 18:55:49 -070087 hnd->lockState = 0;
Mathias Agopian485e6982009-05-05 20:21:57 -070088 hnd->writeOwner = 0;
Mathias Agopian988b8bd2009-05-04 14:26:56 -070089 return 0;
90}
91
92int gralloc_unregister_buffer(gralloc_module_t const* module,
93 buffer_handle_t handle)
94{
95 if (private_handle_t::validate(handle) < 0)
96 return -EINVAL;
97
98 /*
99 * If the buffer has been mapped during a lock operation, it's time
Mathias Agopian51156652009-06-09 18:55:49 -0700100 * to un-map it. It's an error to be here with a locked buffer.
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700101 * NOTE: the framebuffer is handled differently and is never unmapped.
102 */
103
Mathias Agopian51156652009-06-09 18:55:49 -0700104 private_handle_t* hnd = (private_handle_t*)handle;
105 int32_t current_value, new_value;
106 int retry;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700107
Mathias Agopian51156652009-06-09 18:55:49 -0700108 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
109 "handle %p still locked (state=%08x)",
Mathias Agopian485e6982009-05-05 20:21:57 -0700110 hnd, hnd->lockState);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700111
Mathias Agopian51156652009-06-09 18:55:49 -0700112 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
113 gralloc_unmap(module, handle);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700114 }
Mathias Agopian51156652009-06-09 18:55:49 -0700115
116 hnd->base = 0;
117 hnd->lockState = 0;
118 hnd->writeOwner = 0;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700119 return 0;
120}
Mathias Agopiana8a75162009-04-10 14:24:31 -0700121
122int gralloc_lock(gralloc_module_t const* module,
123 buffer_handle_t handle, int usage,
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700124 int l, int t, int w, int h,
125 void** vaddr)
Mathias Agopiana8a75162009-04-10 14:24:31 -0700126{
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700127 if (private_handle_t::validate(handle) < 0)
128 return -EINVAL;
129
130 int err = 0;
Mathias Agopian51156652009-06-09 18:55:49 -0700131 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian485e6982009-05-05 20:21:57 -0700132 int32_t current_value, new_value;
133 int retry;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700134
Mathias Agopian485e6982009-05-05 20:21:57 -0700135 do {
136 current_value = hnd->lockState;
137 new_value = current_value;
Mathias Agopian51156652009-06-09 18:55:49 -0700138
139 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700140 // already locked for write
141 LOGE("handle %p already locked for write", handle);
142 return -EBUSY;
Mathias Agopian51156652009-06-09 18:55:49 -0700143 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700144 // already locked for read
145 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
146 LOGE("handle %p already locked for read", handle);
147 return -EBUSY;
148 } else {
Mathias Agopian82f7c042009-06-03 19:03:26 -0700149 // this is not an error
150 //LOGD("%p already locked for read... count = %d",
151 // handle, (current_value & ~(1<<31)));
Mathias Agopian485e6982009-05-05 20:21:57 -0700152 }
153 }
154
155 // not currently locked
156 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
157 // locking for write
Mathias Agopian51156652009-06-09 18:55:49 -0700158 new_value |= private_handle_t::LOCK_STATE_WRITE;
Mathias Agopian485e6982009-05-05 20:21:57 -0700159 }
160 new_value++;
161
162 retry = android_atomic_cmpxchg(current_value, new_value,
163 (volatile int32_t*)&hnd->lockState);
164 } while (retry);
Mathias Agopian51156652009-06-09 18:55:49 -0700165
166 if (new_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700167 // locking for write, store the tid
168 hnd->writeOwner = gettid();
169 }
170
171 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
Mathias Agopian51156652009-06-09 18:55:49 -0700172 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
173 // we need to map for real
174 pthread_mutex_t* const lock = &sMapLock;
175 pthread_mutex_lock(lock);
176 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
177 err = gralloc_map(module, handle, vaddr);
178 if (err == 0) {
179 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
180 (volatile int32_t*)&(hnd->lockState));
181 }
182 }
183 pthread_mutex_unlock(lock);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700184 }
Mathias Agopian51156652009-06-09 18:55:49 -0700185 *vaddr = (void*)hnd->base;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700186 }
Mathias Agopian485e6982009-05-05 20:21:57 -0700187
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700188 return err;
Mathias Agopiana8a75162009-04-10 14:24:31 -0700189}
190
191int gralloc_unlock(gralloc_module_t const* module,
192 buffer_handle_t handle)
193{
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700194 if (private_handle_t::validate(handle) < 0)
195 return -EINVAL;
196
Mathias Agopian51156652009-06-09 18:55:49 -0700197 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian485e6982009-05-05 20:21:57 -0700198 int32_t current_value, new_value;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700199
Mathias Agopian485e6982009-05-05 20:21:57 -0700200 do {
201 current_value = hnd->lockState;
202 new_value = current_value;
203
Mathias Agopian51156652009-06-09 18:55:49 -0700204 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700205 // locked for write
206 if (hnd->writeOwner == gettid()) {
207 hnd->writeOwner = 0;
Mathias Agopian51156652009-06-09 18:55:49 -0700208 new_value &= ~private_handle_t::LOCK_STATE_WRITE;
Mathias Agopian485e6982009-05-05 20:21:57 -0700209 }
210 }
211
Mathias Agopian51156652009-06-09 18:55:49 -0700212 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700213 LOGE("handle %p not locked", handle);
214 return -EINVAL;
215 }
216
217 new_value--;
218
219 } while (android_atomic_cmpxchg(current_value, new_value,
220 (volatile int32_t*)&hnd->lockState));
221
Mathias Agopiana8a75162009-04-10 14:24:31 -0700222 return 0;
223}