summaryrefslogtreecommitdiffstats
path: root/modules/gralloc/mapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gralloc/mapper.cpp')
-rw-r--r--modules/gralloc/mapper.cpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/modules/gralloc/mapper.cpp b/modules/gralloc/mapper.cpp
new file mode 100644
index 0000000..a5f52ed
--- /dev/null
+++ b/modules/gralloc/mapper.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include "gralloc_priv.h"
+
+/*****************************************************************************/
+
+struct mapped_buffer_t {
+ intptr_t key;
+ int size;
+ int base;
+ int refCount;
+
+ int init(private_handle_t* hnd) {
+ size = hnd->size;
+ base = 0;
+ refCount = 0;
+ struct stat buf;
+ int result = 0;
+ key = intptr_t(hnd);
+ return result;
+ }
+};
+
+static int compare(const mapped_buffer_t& a, const mapped_buffer_t& b) {
+ if (a.key < b.key) {
+ return -1;
+ }
+ if (a.key > b.key) {
+ return 1;
+ }
+ return 0;
+}
+
+struct mapped_buffers_t {
+ pthread_mutex_t mutex;
+ growable_sorted_array_t<mapped_buffer_t> records;
+
+ int map(gralloc_module_t const* module,
+ buffer_handle_t handle,
+ void** vaddr)
+ {
+ private_handle_t* hnd = (private_handle_t*)(handle);
+ mapped_buffer_t key;
+ int result = key.init(hnd);
+ //printRecord(ANDROID_LOG_DEBUG, "map", &key);
+ if (result) {
+ return result;
+ }
+ mapped_buffer_t* record = 0;
+ pthread_mutex_lock(&mutex);
+ // From here to the end of the function we return by jumping to "exit"
+ // so that we always unlock the mutex.
+
+ int index = -1;
+ if (!records.find(key, index)) {
+ //LOGD("New item at %d", index);
+ void* mappedAddress = mmap(0, hnd->size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
+ if (mappedAddress == MAP_FAILED) {
+ result = -errno;
+ //LOGE("map failed %d", result);
+ goto exit;
+ }
+ key.base = intptr_t(mappedAddress);
+ records.insert(index, key);
+ record = records.at(index);
+ } else {
+ //LOGD("Found existing mapping at index %d", index);
+ record = records.at(index);
+ if (record->size != key.size) {
+ LOGE("Requested a new mapping at the same offset"
+ "but with a different size");
+ printRecord(ANDROID_LOG_ERROR, "old", record);
+ printRecord(ANDROID_LOG_ERROR, "new", &key);
+ result = -EINVAL;
+ goto exit;
+ }
+ }
+ record->refCount += 1;
+ hnd->base = record->base;
+ *vaddr = (void*) record->base;
+ exit:
+ //print();
+ pthread_mutex_unlock(&mutex);
+ return result;
+ }
+
+ int unmap(gralloc_module_t const* module,
+ buffer_handle_t handle)
+ {
+ mapped_buffer_t key;
+ key.init((private_handle_t*) handle);
+ //printRecord(ANDROID_LOG_DEBUG, "unmap", &key);
+ int index = -1;
+
+ int result = 0;
+ mapped_buffer_t* record = 0;
+ pthread_mutex_lock(&mutex);
+ // From here to the end of the function we return by jumping to "exit"
+ // so that we always unlock the mutex.
+
+ if (!records.find(key, index)) {
+ // This handle is not currently locked.
+ //LOGE("Could not find existing mapping near %d", index);
+ result = -ENOENT;
+ goto exit;
+ }
+ record = records.at(index);
+ //printRecord(ANDROID_LOG_DEBUG, "record", record);
+ record->refCount -= 1;
+ if (record->refCount == 0) {
+ //LOGD("Unmapping...");
+ if (munmap((void*)record->base, record->size) < 0) {
+ result = -errno;
+ //LOGE("Could not unmap %d", result);
+ }
+ records.remove(index);
+ ((private_handle_t*)handle)->base = 0;
+ }
+
+ exit:
+ //print();
+ pthread_mutex_unlock(&mutex);
+ return result;
+ }
+
+ void print() {
+ char prefix[16];
+ LOGD("Dumping records: count=%d size=%d", records.count, records.size);
+ for(int i=0; i<records.count ; i++) {
+ sprintf(prefix, "%3d", i);
+ printRecord(ANDROID_LOG_DEBUG, prefix, records.at(i));
+ }
+ }
+
+ void printRecord(int level, const char* what, mapped_buffer_t* record) {
+ LOG_PRI(level, LOG_TAG,
+ "%s: key=0x%08x, size=0x%08x, base=0x%08x refCount=%d",
+ what, int(record->key), record->size,
+ record->base, record->refCount);
+ }
+};
+
+static mapped_buffers_t sMappedBuffers = {
+ mutex: PTHREAD_MUTEX_INITIALIZER
+};
+
+/*****************************************************************************/
+
+int gralloc_map(gralloc_module_t const* module,
+ buffer_handle_t handle,
+ void** vaddr)
+{
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ private_handle_t* hnd = (private_handle_t*)(handle);
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+ const private_module_t* m =
+ reinterpret_cast<const private_module_t*>(module);
+ handle = m->framebuffer;
+ }
+
+ int err = sMappedBuffers.map(module, handle, vaddr);
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+ *vaddr = (void*)hnd->base;
+ }
+
+ return err;
+}
+
+int gralloc_unmap(gralloc_module_t const* module,
+ buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ private_handle_t* hnd = (private_handle_t*)(handle);
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+ const private_module_t* m =
+ reinterpret_cast<const private_module_t*>(module);
+ handle = m->framebuffer;
+ }
+
+ return sMappedBuffers.unmap(module, handle);
+}
+
+
+int gralloc_lock(gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h)
+{
+ // FIXME: gralloc_lock() needs implementation
+ return 0;
+}
+
+int gralloc_unlock(gralloc_module_t const* module,
+ buffer_handle_t handle)
+{
+ // FIXME: gralloc_unlock() needs implementation
+ return 0;
+}