gpu_tonemapper: Use individual EGL contexts.

- Use individual EGL contexts for each tone-mapping
  session.
- Having one context make multiple sessions serial, this
  helps in making this parallel when possible.
- Resolves error messages which happened when the context
  was deleted during mirroring.

Change-Id: Ia8738551b4189dccffb233320a9d69fcfd7f0118
Crs-fixed: 1115057
diff --git a/gpu_tonemapper/TonemapFactory.cpp b/gpu_tonemapper/TonemapFactory.cpp
index cffc33a..799a23f 100644
--- a/gpu_tonemapper/TonemapFactory.cpp
+++ b/gpu_tonemapper/TonemapFactory.cpp
@@ -27,9 +27,6 @@
                                           void *lutXform, int lutXformSize)
 //----------------------------------------------------------------------------------------------------------------------------------------------------------
 {
-  // initializes the engine - does nothing if already initialized
-  engine_initialize();
-
   // build the tonemapper
   Tonemapper *tonemapper = Tonemapper::build(type, colorMap, colorMapSize, lutXform, lutXformSize);
 
@@ -40,6 +37,4 @@
 void TonemapperFactory_Destroy()
 //------------------------------------------
 {
-  // shutdown the engine
-  engine_shutdown();
 }
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
index bb7ba1b..b4d82e1 100644
--- a/gpu_tonemapper/Tonemapper.cpp
+++ b/gpu_tonemapper/Tonemapper.cpp
@@ -39,7 +39,7 @@
 Tonemapper::~Tonemapper()
 //-----------------------------------------------------------------------------
 {
-  engine_bind();
+  engine_bind(engineContext);
   engine_deleteInputBuffer(tonemapTexture);
   engine_deleteInputBuffer(lutXformTexture);
   engine_deleteProgram(programID);
@@ -50,6 +50,8 @@
     delete eglImageWrapper;
     eglImageWrapper = 0;
   }
+
+  engine_shutdown(engineContext);
 }
 
 //-----------------------------------------------------------------------------
@@ -61,10 +63,14 @@
       ALOGE("Invalid Color Map size = %d", colorMapSize);
       return NULL;
   }
-  engine_bind();
 
   // build new tonemapper
   Tonemapper *tonemapper = new Tonemapper();
+
+  tonemapper->engineContext = engine_initialize();
+
+  engine_bind(tonemapper->engineContext);
+
   // load the 3d lut
   tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
   // load the non-uniform xform
@@ -101,7 +107,7 @@
 //-----------------------------------------------------------------------------
 {
   // make current
-  engine_bind();
+  engine_bind(engineContext);
 
   // create eglimages if required
   EGLImageBuffer *dst_buffer = eglImageWrapper->wrap(dst);
diff --git a/gpu_tonemapper/Tonemapper.h b/gpu_tonemapper/Tonemapper.h
index 0f9bd51..1d6f808 100644
--- a/gpu_tonemapper/Tonemapper.h
+++ b/gpu_tonemapper/Tonemapper.h
@@ -24,9 +24,11 @@
 #define TONEMAP_INVERSE 1
 
 #include "EGLImageWrapper.h"
+#include "engine.h"
 
 class Tonemapper {
  private:
+  void* engineContext;
   unsigned int tonemapTexture;
   unsigned int lutXformTexture;
   unsigned int programID;
diff --git a/gpu_tonemapper/engine.h b/gpu_tonemapper/engine.h
index 5635ee3..ca914b2 100644
--- a/gpu_tonemapper/engine.h
+++ b/gpu_tonemapper/engine.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -20,9 +20,9 @@
 #ifndef __TONEMAPPER_ENGINE_H__
 #define __TONEMAPPER_ENGINE_H__
 
-bool engine_initialize();
-void engine_bind();
-void engine_shutdown();
+void* engine_initialize();
+void engine_bind(void*);
+void engine_shutdown(void*);
 
 unsigned int engine_loadProgram(int, const char **, int, const char **);
 void engine_setProgram(int);
@@ -39,4 +39,4 @@
 
 int engine_blit(int);
 
-#endif  //__TONEMAPPER_ENGINE_H__
\ No newline at end of file
+#endif  //__TONEMAPPER_ENGINE_H__
diff --git a/gpu_tonemapper/glengine.cpp b/gpu_tonemapper/glengine.cpp
index e5c8e68..9fc8f6b 100644
--- a/gpu_tonemapper/glengine.cpp
+++ b/gpu_tonemapper/glengine.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -24,37 +24,42 @@
 void checkGlError(const char *, int);
 void checkEglError(const char *, int);
 
-static EGLDisplay eglDisplay;
-static EGLContext eglContext;
-static EGLSurface eglSurface;
-
-static bool isEngineInitialized = false;
+class EngineContext {
+    public:
+    EGLDisplay eglDisplay;
+    EGLContext eglContext;
+    EGLSurface eglSurface;
+    EngineContext()
+    {
+        eglDisplay = EGL_NO_DISPLAY;
+        eglContext = EGL_NO_CONTEXT;
+        eglSurface = EGL_NO_SURFACE;
+    }
+};
 
 //-----------------------------------------------------------------------------
 // Make Current
-void engine_bind()
+void engine_bind(void* context)
 //-----------------------------------------------------------------------------
 {
-  EGL(eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext));
+  EngineContext* engineContext = (EngineContext*)(context);
+  EGL(eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext));
 }
 
 //-----------------------------------------------------------------------------
 // initialize GL
 //
-bool engine_initialize()
+void* engine_initialize()
 //-----------------------------------------------------------------------------
 {
-  if (isEngineInitialized)
-    return true;
-
-  EGLBoolean result = false;
+  EngineContext* engineContext = new EngineContext();
 
   // display
-  eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  engineContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   EGL(eglBindAPI(EGL_OPENGL_ES_API));
 
   // initialize
-  EGL(eglInitialize(eglDisplay, 0, 0));
+  EGL(eglInitialize(engineContext->eglDisplay, 0, 0));
 
   // config
   EGLConfig eglConfig;
@@ -65,38 +70,36 @@
                                   EGL_ALPHA_SIZE,   8,
                                   EGL_NONE};
   int numConfig = 0;
-  EGL(eglChooseConfig(eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
+  EGL(eglChooseConfig(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
 
   // context
   EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
-  eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, eglContextAttribList);
+  engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
 
   // surface
   EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
-  eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, eglSurfaceAttribList);
+  engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
 
-  result = (EGL_TRUE == eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext));
+  eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
 
-  isEngineInitialized = result;
+  ALOGI("In %s context = %p", __FUNCTION__, (void *)(engineContext->eglContext));
 
-  ALOGI("In %s result = %d context = %p", __FUNCTION__, result, (void *)eglContext);
-
-  return result;
+  return (void*)(engineContext);
 }
 
 //-----------------------------------------------------------------------------
 // Shutdown.
-void engine_shutdown()
+void engine_shutdown(void* context)
 //-----------------------------------------------------------------------------
 {
-  EGL(eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
-  EGL(eglDestroySurface(eglDisplay, eglSurface));
-  EGL(eglDestroyContext(eglDisplay, eglContext));
-  EGL(eglTerminate(eglDisplay));
-  eglDisplay = EGL_NO_DISPLAY;
-  eglContext = EGL_NO_CONTEXT;
-  eglSurface = EGL_NO_SURFACE;
-  isEngineInitialized = false;
+  EngineContext* engineContext = (EngineContext*)context;
+  EGL(eglMakeCurrent(engineContext->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+  EGL(eglDestroySurface(engineContext->eglDisplay, engineContext->eglSurface));
+  EGL(eglDestroyContext(engineContext->eglDisplay, engineContext->eglContext));
+  EGL(eglTerminate(engineContext->eglDisplay));
+  engineContext->eglDisplay = EGL_NO_DISPLAY;
+  engineContext->eglContext = EGL_NO_CONTEXT;
+  engineContext->eglSurface = EGL_NO_SURFACE;
 }
 
 //-----------------------------------------------------------------------------
@@ -206,14 +209,14 @@
   if (fd != -1) {
     EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
 
-    EGLSyncKHR sync = eglCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+    EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
 
     if (sync == EGL_NO_SYNC_KHR) {
       ALOGE("%s - Failed to Create sync from source fd", __FUNCTION__);
     } else {
       // the gpu will wait for this sync - not this cpu thread.
-      EGL(eglWaitSyncKHR(eglDisplay, sync, 0));
-      EGL(eglDestroySyncKHR(eglDisplay, sync));
+      EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
+      EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
     }
   }
 }
@@ -224,16 +227,16 @@
 {
   int fd = -1;
 
-  EGLSyncKHR sync = eglCreateSyncKHR(eglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+  EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
   GL(glFlush());
   if (sync == EGL_NO_SYNC_KHR) {
     ALOGE("%s - Failed to Create Native Fence sync", __FUNCTION__);
   } else {
-    fd = eglDupNativeFenceFDANDROID(eglDisplay, sync);
+    fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
     if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
       ALOGE("%s - Failed to dup sync", __FUNCTION__);
     }
-    EGL(eglDestroySyncKHR(eglDisplay, sync));
+    EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
   }
 
   return fd;