initial GL libraries for msm8960
Change-Id: I16451c70a079894ac326d3564d96f1fbafcd4f1b
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
new file mode 100644
index 0000000..9ff0a5e
--- /dev/null
+++ b/libgralloc/ionalloc.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <linux/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <errno.h>
+#include "gralloc_priv.h"
+#include "ionalloc.h"
+
+using gralloc::IonAlloc;
+
+#define ION_DEVICE "/dev/ion"
+
+int IonAlloc::open_device()
+{
+ if(mIonFd == FD_INIT)
+ mIonFd = open(ION_DEVICE, O_RDONLY);
+
+ if(mIonFd < 0 ) {
+ ALOGE("%s: Failed to open ion device - %s",
+ __FUNCTION__, strerror(errno));
+ mIonFd = FD_INIT;
+ return -errno;
+ }
+ return 0;
+}
+
+void IonAlloc::close_device()
+{
+ if(mIonFd >= 0)
+ close(mIonFd);
+ mIonFd = FD_INIT;
+}
+
+int IonAlloc::alloc_buffer(alloc_data& data)
+{
+ int err = 0;
+ int ionSyncFd = FD_INIT;
+ int iFd = FD_INIT;
+ struct ion_handle_data handle_data;
+ struct ion_fd_data fd_data;
+ struct ion_allocation_data ionAllocData;
+
+ void *base = 0;
+
+ ionAllocData.len = data.size;
+ ionAllocData.align = data.align;
+ ionAllocData.flags = data.flags;
+
+ err = open_device();
+ if (err)
+ return err;
+
+ if(data.uncached) {
+ // Use the sync FD to alloc and map
+ // when we need uncached memory
+ // FIX: О–DSYNC defined to open uncached - add that in kernel
+ //ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC);
+ ionSyncFd = open(ION_DEVICE, O_RDONLY);
+ if(ionSyncFd < 0) {
+ ALOGE("%s: Failed to open ion device - %s",
+ __FUNCTION__, strerror(errno));
+ return -errno;
+ }
+ iFd = ionSyncFd;
+ } else {
+ iFd = mIonFd;
+ }
+
+ if(ioctl(iFd, ION_IOC_ALLOC, &ionAllocData)) {
+ err = -errno;
+ ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
+ if(ionSyncFd >= 0)
+ close(ionSyncFd);
+ ionSyncFd = FD_INIT;
+ return err;
+ }
+
+ fd_data.handle = ionAllocData.handle;
+ handle_data.handle = ionAllocData.handle;
+ if(ioctl(iFd, ION_IOC_MAP, &fd_data)) {
+ err = -errno;
+ ALOGE("%s: ION_IOC_MAP failed with error - %s",
+ __FUNCTION__, strerror(errno));
+ ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+ if(ionSyncFd >= 0)
+ close(ionSyncFd);
+ ionSyncFd = FD_INIT;
+ return err;
+ }
+
+ //if(!(data.flags & ION_SECURE) &&
+ if(!(data.allocType & private_handle_t::PRIV_FLAGS_NOT_MAPPED)) {
+
+ base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd_data.fd, 0);
+ if(base == MAP_FAILED) {
+ err = -errno;
+ ALOGE("%s: Failed to map the allocated memory: %s",
+ __FUNCTION__, strerror(errno));
+ ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+ ionSyncFd = FD_INIT;
+ return err;
+ }
+ memset(base, 0, ionAllocData.len);
+ // Clean cache after memset
+ clean_buffer(base, data.size, data.offset, fd_data.fd);
+ }
+
+ //Close the uncached FD since we no longer need it;
+ if(ionSyncFd >= 0)
+ close(ionSyncFd);
+ ionSyncFd = FD_INIT;
+
+ data.base = base;
+ data.fd = fd_data.fd;
+ ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+ ALOGD("ion: Allocated buffer base:%p size:%d fd:%d",
+ data.base, ionAllocData.len, data.fd);
+ return 0;
+}
+
+
+int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd)
+{
+ ALOGD("ion: Freeing buffer base:%p size:%d fd:%d",
+ base, size, fd);
+ int err = 0;
+ err = open_device();
+ if (err)
+ return err;
+
+ if(base)
+ err = unmap_buffer(base, size, offset);
+ close(fd);
+ return err;
+}
+
+int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
+{
+ int err = 0;
+ void *base = 0;
+ // It is a (quirky) requirement of ION to have opened the
+ // ion fd in the process that is doing the mapping
+ err = open_device();
+ if (err)
+ return err;
+
+ base = mmap(0, size, PROT_READ| PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ *pBase = base;
+ if(base == MAP_FAILED) {
+ err = -errno;
+ ALOGD("ion: Failed to map memory in the client: %s",
+ strerror(errno));
+ } else {
+ ALOGD("ion: Mapped buffer base:%p size:%d offset:%d fd:%d",
+ base, size, offset, fd);
+ }
+ return err;
+}
+
+int IonAlloc::unmap_buffer(void *base, size_t size, int offset)
+{
+ ALOGD("ion: Unmapping buffer base:%p size:%d", base, size);
+ int err = 0;
+ if(munmap(base, size)) {
+ err = -errno;
+ ALOGE("ion: Failed to unmap memory at %p : %s",
+ base, strerror(errno));
+ }
+ return err;
+
+}
+int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
+{
+ struct ion_flush_data flush_data;
+ struct ion_fd_data fd_data;
+ struct ion_handle_data handle_data;
+ struct ion_handle* handle;
+ int err = 0;
+
+ err = open_device();
+ if (err)
+ return err;
+
+ fd_data.fd = fd;
+ if (ioctl(mIonFd, ION_IOC_IMPORT, &fd_data)) {
+ err = -errno;
+ ALOGE("%s: ION_IOC_IMPORT failed with error - %s",
+ __FUNCTION__, strerror(errno));
+ return err;
+ }
+
+ handle_data.handle = fd_data.handle;
+ flush_data.handle = fd_data.handle;
+ flush_data.vaddr = base;
+ flush_data.offset = offset;
+ flush_data.length = size;
+ if(ioctl(mIonFd, ION_IOC_CLEAN_INV_CACHES, &flush_data)) {
+ err = -errno;
+ ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s",
+ __FUNCTION__, strerror(errno));
+ ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+ return err;
+ }
+ ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+ return 0;
+}
+