display: Use ion cookie in GPU Tonemapper

- The fd's used for book-keeping can change when the clients
  close and reopen sessions, hence they are not reliable and
  can lead to incorrect virtual address usage causing
  corruption or stale data.
- Hence use ion cookie for book-keeping which is unique for a
  given memory fd.
- Use LRU method free up/reuse on reaching max limit.
- Remove Tonemapper_destroy which is not needed anymore.

Change-Id: I5777649b34210977c18ce20c65e0aa2baa8e7d26
Crs-fixed: 1110175
diff --git a/gpu_tonemapper/Android.mk b/gpu_tonemapper/Android.mk
index 9ae3840..1a5ff75 100644
--- a/gpu_tonemapper/Android.mk
+++ b/gpu_tonemapper/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_MODULE              := libgpu_tonemapper
 LOCAL_MODULE_TAGS         := optional
 LOCAL_C_INCLUDES          := $(TARGET_OUT_HEADERS)/qcom/display/
+LOCAL_C_INCLUDES          += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
 
 LOCAL_CFLAGS              := -Wno-missing-field-initializers -Wall \
                              -Wno-unused-parameter -std=c++11 -DLOG_TAG=\"GPU_TONEMAPPER\"
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
index 298475f..18465b8 100644
--- a/gpu_tonemapper/EGLImageWrapper.cpp
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -21,21 +21,101 @@
 #include <cutils/native_handle.h>
 #include <gralloc_priv.h>
 #include <ui/GraphicBuffer.h>
+#include <fcntl.h>
+#include <linux/msm_ion.h>
 
 //-----------------------------------------------------------------------------
-EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
+void free_ion_cookie(int ion_fd, int cookie)
 //-----------------------------------------------------------------------------
 {
-  const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
+  if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
+  } else {
+      ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
+  }
+}
 
-  EGLImageBuffer *result = 0;
-  std::map<int, EGLImageBuffer *>::iterator it = eglImageBufferMap.find(src->fd);
-  if (it == eglImageBufferMap.end()) {
+//-----------------------------------------------------------------------------
+int get_ion_cookie(int ion_fd, int fd)
+//-----------------------------------------------------------------------------
+{
+   int cookie = fd;
+
+   struct ion_fd_data fdData;
+   memset(&fdData, 0, sizeof(fdData));
+   fdData.fd = fd;
+
+   if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
+        cookie = fdData.handle;
+   } else {
+        ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
+   }
+
+   return cookie;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::DeleteEGLImageCallback::DeleteEGLImageCallback(int fd)
+//-----------------------------------------------------------------------------
+{
+    ion_fd = fd;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& k, EGLImageBuffer*& eglImage)
+//-----------------------------------------------------------------------------
+{
+    free_ion_cookie(ion_fd,  k);
+    if( eglImage != 0 )
+    {
+        delete eglImage;
+    }
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::EGLImageWrapper()
+//-----------------------------------------------------------------------------
+{
+    eglImageBufferMap = new android::LruCache<int, EGLImageBuffer*>(32);
+    ion_fd = open("/dev/ion", O_RDONLY);
+    callback = new DeleteEGLImageCallback(ion_fd);
+    eglImageBufferMap->setOnEntryRemovedListener(callback);
+}
+
+//-----------------------------------------------------------------------------
+EGLImageWrapper::~EGLImageWrapper()
+//-----------------------------------------------------------------------------
+{
+    if( eglImageBufferMap != 0 )
+    {
+        eglImageBufferMap->clear();
+        delete eglImageBufferMap;
+        eglImageBufferMap = 0;
+    }
+
+    if( callback != 0 )
+    {
+        delete callback;
+        callback = 0;
+    }
+
+    if( ion_fd > 0 )
+    {
+        close(ion_fd);
+    }
+    ion_fd = -1;
+}
+//-----------------------------------------------------------------------------
+static EGLImageBuffer* L_wrap(const private_handle_t *src)
+//-----------------------------------------------------------------------------
+{
+    EGLImageBuffer* result = 0;
+
     native_handle_t *native_handle = const_cast<private_handle_t *>(src);
 
     int flags = android::GraphicBuffer::USAGE_HW_TEXTURE |
                 android::GraphicBuffer::USAGE_SW_READ_NEVER |
                 android::GraphicBuffer::USAGE_SW_WRITE_NEVER;
+
     if (src->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
       flags |= android::GraphicBuffer::USAGE_PROTECTED;
     }
@@ -46,21 +126,25 @@
 
     result = new EGLImageBuffer(graphicBuffer);
 
-    eglImageBufferMap[src->fd] = result;
-  } else {
-    result = it->second;
-  }
-
-  return result;
+    return result;
 }
 
 //-----------------------------------------------------------------------------
-void EGLImageWrapper::destroy()
+EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
 //-----------------------------------------------------------------------------
 {
-  std::map<int, EGLImageBuffer *>::iterator it = eglImageBufferMap.begin();
-  for (; it != eglImageBufferMap.end(); it++) {
-    delete it->second;
-  }
-  eglImageBufferMap.clear();
+    const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
+
+    int ion_cookie = get_ion_cookie(ion_fd, src->fd);
+    EGLImageBuffer* eglImage = eglImageBufferMap->get(ion_cookie);
+    if( eglImage == 0 )
+    {
+        eglImage = L_wrap(src);
+        eglImageBufferMap->put(ion_cookie, eglImage);
+    }
+    else {
+        free_ion_cookie(ion_fd, ion_cookie);
+    }
+
+    return eglImage;
 }
diff --git a/gpu_tonemapper/EGLImageWrapper.h b/gpu_tonemapper/EGLImageWrapper.h
index 90aaf58..e9a4d68 100644
--- a/gpu_tonemapper/EGLImageWrapper.h
+++ b/gpu_tonemapper/EGLImageWrapper.h
@@ -20,15 +20,28 @@
 #ifndef __TONEMAPPER_EGLIMAGEWRAPPER_H__
 #define __TONEMAPPER_EGLIMAGEWRAPPER_H__
 
-#include <map>
+#include <utils/LruCache.h>
 #include "EGLImageBuffer.h"
 
 class EGLImageWrapper {
-  std::map<int, EGLImageBuffer *> eglImageBufferMap;
+    private:
+        class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*>
+        {
+        private:
+          int ion_fd;
+        public:
+          DeleteEGLImageCallback(int ion_fd);
+          void operator()(int& ion_cookie, EGLImageBuffer*& eglImage);
+        };
 
- public:
-  EGLImageBuffer *wrap(const void *pvt_handle);
-  void destroy();
+        android::LruCache<int, EGLImageBuffer *>* eglImageBufferMap;
+        DeleteEGLImageCallback* callback;
+        int ion_fd;
+
+    public:
+        EGLImageWrapper();
+        ~EGLImageWrapper();
+        EGLImageBuffer* wrap(const void *pvt_handle);
 };
 
 #endif  //__TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/gpu_tonemapper/TonemapFactory.cpp b/gpu_tonemapper/TonemapFactory.cpp
index 799a23f..5aae697 100644
--- a/gpu_tonemapper/TonemapFactory.cpp
+++ b/gpu_tonemapper/TonemapFactory.cpp
@@ -32,9 +32,3 @@
 
   return tonemapper;
 }
-
-//------------------------------------------
-void TonemapperFactory_Destroy()
-//------------------------------------------
-{
-}
diff --git a/gpu_tonemapper/TonemapFactory.h b/gpu_tonemapper/TonemapFactory.h
index 1004170..404f4cd 100644
--- a/gpu_tonemapper/TonemapFactory.h
+++ b/gpu_tonemapper/TonemapFactory.h
@@ -30,9 +30,6 @@
 Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
                                           void *lutXform, int lutXformSize);
 
-// destroy tonemap session
-void TonemapperFactory_Destroy();
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
index b4d82e1..ec74b80 100644
--- a/gpu_tonemapper/Tonemapper.cpp
+++ b/gpu_tonemapper/Tonemapper.cpp
@@ -46,7 +46,6 @@
 
   // clear EGLImage mappings
   if (eglImageWrapper != 0) {
-    eglImageWrapper->destroy();
     delete eglImageWrapper;
     eglImageWrapper = 0;
   }