Align secure video surfaces to 1 MB
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / gralloc / gralloc.cpp
index c43ce4112bb5f10c68ae29fb8ef131d3d1a49d34..d10dc274af7484b3aa8bfb4785e19e15b25eb3b2 100644 (file)
 #include "exynos_format.h"
 #include "gr.h"
 
+#define ION_HEAP_EXYNOS_CONTIG_MASK     (1 << 4)
+#define ION_EXYNOS_FIMD_VIDEO_MASK  (1 << 28)
+#define ION_EXYNOS_MFC_OUTPUT_MASK  (1 << 26)
+#define ION_EXYNOS_MFC_INPUT_MASK   (1 << 25)
+#define MB_1 (1024*1024)
+
+
 /*****************************************************************************/
 
 struct gralloc_context_t {
@@ -84,38 +91,50 @@ open: gralloc_device_open
 
 struct private_module_t HAL_MODULE_INFO_SYM = {
 base: {
-common: {
-tag: HARDWARE_MODULE_TAG,
-     version_major: 1,
-     version_minor: 0,
-     id: GRALLOC_HARDWARE_MODULE_ID,
-     name: "Graphics Memory Allocator Module",
-     author: "The Android Open Source Project",
-     methods: &gralloc_module_methods
-        },
-registerBuffer: gralloc_register_buffer,
-                unregisterBuffer: gralloc_unregister_buffer,
-                lock: gralloc_lock,
-                unlock: gralloc_unlock,
-      },
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        version_major: 1,
+        version_minor: 0,
+        id: GRALLOC_HARDWARE_MODULE_ID,
+        name: "Graphics Memory Allocator Module",
+        author: "The Android Open Source Project",
+        methods: &gralloc_module_methods
+    },
+    registerBuffer: gralloc_register_buffer,
+    unregisterBuffer: gralloc_unregister_buffer,
+    lock: gralloc_lock,
+    unlock: gralloc_unlock,
+},
 framebuffer: 0,
-             flags: 0,
-             numBuffers: 0,
-             bufferMask: 0,
-             lock: PTHREAD_MUTEX_INITIALIZER,
-             currentBuffer: 0,
-             ionfd: -1,
+flags: 0,
+numBuffers: 0,
+bufferMask: 0,
+lock: PTHREAD_MUTEX_INITIALIZER,
+currentBuffer: 0,
+ionfd: -1,
 };
 
 /*****************************************************************************/
 
-#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
+static unsigned int _select_heap(int usage)
+{
+    unsigned int heap_mask;
+
+    if (usage & GRALLOC_USAGE_PROTECTED)
+        heap_mask = ION_HEAP_EXYNOS_CONTIG_MASK;
+    else
+        heap_mask = ION_HEAP_SYSTEM_MASK;
+
+    return heap_mask;
+}
 
 static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int usage,
                              unsigned int ion_flags, private_handle_t **hnd, int *stride)
 {
-    size_t size, bpr;
+    size_t size, bpr, alignment = 0;
     int bpp = 0, vstride, fd, err;
+    unsigned int heap_mask = _select_heap(usage);
+
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
@@ -132,18 +151,31 @@ static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int usage,
             bpp = 2;
             break;
         case HAL_PIXEL_FORMAT_BLOB:
-            bpp = 1;
+            *stride = w;
+            vstride = h;
+            size = w * h;
             break;
         default:
             return -EINVAL;
     }
-    bpr = ALIGN(w*bpp, 16);
-    vstride = ALIGN(h, 16);
-    size = bpr * vstride;
-    *stride = bpr / bpp;
-    size = ALIGN(size, PAGE_SIZE);
 
-    err = ion_alloc_fd(ionfd, size, 0, 1 << ION_HEAP_TYPE_SYSTEM, ion_flags,
+    if (format != HAL_PIXEL_FORMAT_BLOB) {
+        bpr = ALIGN(w*bpp, 16);
+        vstride = ALIGN(h, 16);
+        if (vstride < h + 2)
+            size = bpr * (h + 2);
+        else
+            size = bpr * vstride;
+        *stride = bpr / bpp;
+        size = ALIGN(size, PAGE_SIZE);
+    }
+
+    if (usage & GRALLOC_USAGE_PROTECTED) {
+        alignment = MB_1;
+        ion_flags |= ION_EXYNOS_FIMD_VIDEO_MASK;
+    }
+
+    err = ion_alloc_fd(ionfd, size, alignment, heap_mask, ion_flags,
                        &fd);
     *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride,
                                 vstride);
@@ -151,58 +183,119 @@ static int gralloc_alloc_rgb(int ionfd, int w, int h, int format, int usage,
     return err;
 }
 
-static int gralloc_alloc_yuv(int ionfd, int w, int h, int format, int usage,
-                             unsigned int ion_flags, private_handle_t **hnd, int *stride)
+static int gralloc_alloc_framework_yuv(int ionfd, int w, int h, int format,
+                                       int usage, unsigned int ion_flags,
+                                       private_handle_t **hnd, int *stride)
 {
-    size_t luma_size, chroma_size;
-    int err, planes, fd, fd1, fd2 = 0;
-    size_t luma_vstride;
-    *stride = ALIGN(w, 16);
+    size_t size;
+    int err, fd;
 
     switch (format) {
-        ALOGE("invalid yuv format %d\n", format);
         case HAL_PIXEL_FORMAT_YV12:
-        {
-            luma_vstride = ALIGN(h, 16);
-            luma_size = luma_vstride * *stride;
-            chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16);
-            planes = 3;
+            *stride = ALIGN(w, 16);
             break;
-        }
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
-        {
-            size_t chroma_vstride = ALIGN(h / 2, 32);
-            luma_vstride = ALIGN(h, 32);
-            luma_size = luma_vstride * *stride;
-            chroma_size = chroma_vstride * *stride;
-            planes = 2;
+            *stride = w;
             break;
-        }
         default:
-        ALOGE("invalid yuv format %d\n", format);
-        return -EINVAL;
+            ALOGE("invalid yuv format %d\n", format);
+            return -EINVAL;
     }
 
-    err = ion_alloc_fd(ionfd, luma_size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
+    size = *stride * h * 3 / 2;
+    err = ion_alloc_fd(ionfd, size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
                        ion_flags, &fd);
     if (err)
         return err;
-    err = ion_alloc_fd(ionfd, chroma_size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
-                       ion_flags,
-                       &fd1);
+
+    *hnd = new private_handle_t(fd, size, usage, w, h, format, *stride, h);
+    return err;
+}
+
+static int gralloc_alloc_yuv(int ionfd, int w, int h, int format,
+                             int usage, unsigned int ion_flags,
+                             private_handle_t **hnd, int *stride)
+{
+    size_t luma_size, chroma_size;
+    int err, planes, fd, fd1, fd2 = 0;
+    size_t luma_vstride;
+    unsigned int heap_mask = _select_heap(usage);
+
+    *stride = ALIGN(w, 16);
+
+    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+        ALOGV("HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED : usage(%x), flags(%x)\n", usage, ion_flags);
+        if ((usage & GRALLOC_USAGE_HW_CAMERA_ZSL) == GRALLOC_USAGE_HW_CAMERA_ZSL) {
+            format = HAL_PIXEL_FORMAT_YCbCr_422_I; // YUYV
+        } else if (usage & GRALLOC_USAGE_HW_TEXTURE) {
+            format = HAL_PIXEL_FORMAT_EXYNOS_YV12;
+        } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+            format = HAL_PIXEL_FORMAT_YCbCr_420_SP; // NV12M
+        }
+    }
+    switch (format) {
+        case HAL_PIXEL_FORMAT_EXYNOS_YV12:
+            {
+                *stride = ALIGN(w, 32);
+                luma_vstride = ALIGN(h, 16);
+                luma_size = luma_vstride * *stride;
+                chroma_size = (luma_vstride / 2) * ALIGN(*stride / 2, 16);
+                planes = 3;
+                break;
+            }
+        case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+            {
+                size_t chroma_vstride = ALIGN(h / 2, 32);
+                luma_vstride = ALIGN(h, 32);
+                luma_size = luma_vstride * *stride;
+                chroma_size = chroma_vstride * *stride;
+                planes = 2;
+                break;
+            }
+        case HAL_PIXEL_FORMAT_YV12:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            return gralloc_alloc_framework_yuv(ionfd, w, h, format, usage,
+                                               ion_flags, hnd, stride);
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            {
+                luma_vstride = h;
+                luma_size = luma_vstride * *stride * 2;
+                chroma_size = 0;
+                planes = 1;
+                break;
+            }
+        default:
+            ALOGE("invalid yuv format %d\n", format);
+            return -EINVAL;
+    }
+
+    if (usage & GRALLOC_USAGE_PROTECTED)
+       ion_flags |= ION_EXYNOS_MFC_OUTPUT_MASK;
+
+    err = ion_alloc_fd(ionfd, luma_size, 0, heap_mask, ion_flags, &fd);
     if (err)
-        goto err1;
-    if (planes == 3) {
-        err = ion_alloc_fd(ionfd, chroma_size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
-                           ion_flags, &fd2);
+        return err;
+    if (planes == 1) {
+        *hnd = new private_handle_t(fd, luma_size, usage, w, h,
+                                    format, *stride, luma_vstride);
+    } else {
+        err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd1);
         if (err)
-            goto err2;
+            goto err1;
+        if (planes == 3) {
+            err = ion_alloc_fd(ionfd, chroma_size, 0, heap_mask, ion_flags, &fd2);
+            if (err)
+                goto err2;
+
+            *hnd = new private_handle_t(fd, fd1, fd2, luma_size, usage, w, h,
+                                        format, *stride, luma_vstride);
+        } else {
+            *hnd = new private_handle_t(fd, fd1, luma_size, usage, w, h, format,
+                                        *stride, luma_vstride);
+        }
     }
-
-    *hnd = new private_handle_t(fd, fd1, fd2, luma_size, usage, w, h, format,
-                                *stride, luma_vstride);
     return err;
 
 err2:
@@ -219,13 +312,13 @@ static int gralloc_alloc(alloc_device_t* dev,
     int stride;
     int err;
     unsigned int ion_flags = 0;
-    private_handle_t *hnd;
+    private_handle_t *hnd = NULL;
 
     if (!pHandle || !pStride)
         return -EINVAL;
 
     if( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN )
-        ion_flags = ION_FLAG_CACHED;
+        ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
 
     private_module_t* m = reinterpret_cast<private_module_t*>
         (dev->common.module);
@@ -240,8 +333,6 @@ static int gralloc_alloc(alloc_device_t* dev,
     if (err)
         return err;
 
-    err = grallocMap(module, hnd);
-
     if (err != 0)
         goto err;
 
@@ -249,10 +340,12 @@ static int gralloc_alloc(alloc_device_t* dev,
     *pStride = stride;
     return 0;
 err:
+    if (!hnd)
+        return err;
     close(hnd->fd);
-    if (hnd->fd1 > 0)
+    if (hnd->fd1 >= 0)
         close(hnd->fd1);
-    if (hnd->fd2 > 0)
+    if (hnd->fd2 >= 0)
         close(hnd->fd2);
     return err;
 }
@@ -266,12 +359,13 @@ static int gralloc_free(alloc_device_t* dev,
     private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
     gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
                                                                    dev->common.module);
+    if (hnd->base)
+        grallocUnmap(module, const_cast<private_handle_t*>(hnd));
 
-    grallocUnmap(module, const_cast<private_handle_t*>(hnd));
     close(hnd->fd);
-    if (hnd->fd1 > 0)
+    if (hnd->fd1 >= 0)
         close(hnd->fd1);
-    if (hnd->fd2 > 0)
+    if (hnd->fd2 >= 0)
         close(hnd->fd2);
 
     delete hnd;