gpu_tonemapper: Include gpu tonemapper
GPU tonemapper library which is used by HWC to tone
map the layers from one Gamut to another based on the
3D LUT.
Change-Id: Iccaa38e40989e832fd3891a24eca494aba696d9a
Crs-fixed: 1094964
diff --git a/gpu_tonemapper/glengine.cpp b/gpu_tonemapper/glengine.cpp
new file mode 100644
index 0000000..e5c8e68
--- /dev/null
+++ b/gpu_tonemapper/glengine.cpp
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright 2015 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 "glengine.h"
+#include <utils/Log.h>
+#include "engine.h"
+
+void checkGlError(const char *, int);
+void checkEglError(const char *, int);
+
+static EGLDisplay eglDisplay;
+static EGLContext eglContext;
+static EGLSurface eglSurface;
+
+static bool isEngineInitialized = false;
+
+//-----------------------------------------------------------------------------
+// Make Current
+void engine_bind()
+//-----------------------------------------------------------------------------
+{
+ EGL(eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext));
+}
+
+//-----------------------------------------------------------------------------
+// initialize GL
+//
+bool engine_initialize()
+//-----------------------------------------------------------------------------
+{
+ if (isEngineInitialized)
+ return true;
+
+ EGLBoolean result = false;
+
+ // display
+ eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ EGL(eglBindAPI(EGL_OPENGL_ES_API));
+
+ // initialize
+ EGL(eglInitialize(eglDisplay, 0, 0));
+
+ // config
+ EGLConfig eglConfig;
+ EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE};
+ int numConfig = 0;
+ EGL(eglChooseConfig(eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
+
+ // context
+ EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+ eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, eglContextAttribList);
+
+ // surface
+ EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
+ eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, eglSurfaceAttribList);
+
+ result = (EGL_TRUE == eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext));
+
+ isEngineInitialized = result;
+
+ ALOGI("In %s result = %d context = %p", __FUNCTION__, result, (void *)eglContext);
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// Shutdown.
+void engine_shutdown()
+//-----------------------------------------------------------------------------
+{
+ 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;
+}
+
+//-----------------------------------------------------------------------------
+void engine_deleteInputBuffer(unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ if (id != 0) {
+ GL(glDeleteTextures(1, &id));
+ }
+}
+
+//-----------------------------------------------------------------------------
+void engine_deleteProgram(unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ if (id != 0) {
+ GL(glDeleteProgram(id));
+ }
+}
+
+//-----------------------------------------------------------------------------
+unsigned int engine_load3DTexture(void *colorMapData, int sz, int format)
+//-----------------------------------------------------------------------------
+{
+ GLuint texture = 0;
+ GL(glGenTextures(1, &texture));
+ GL(glBindTexture(GL_TEXTURE_3D, texture));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+
+ GL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB10_A2, sz, sz, sz, 0, GL_RGBA,
+ GL_UNSIGNED_INT_2_10_10_10_REV, colorMapData));
+
+ return texture;
+}
+//-----------------------------------------------------------------------------
+unsigned int engine_load1DTexture(void *data, int sz, int format)
+//-----------------------------------------------------------------------------
+{
+ GLuint texture = 0;
+ if ((data != 0) && (sz != 0)) {
+ GL(glGenTextures(1, &texture));
+ GL(glBindTexture(GL_TEXTURE_2D, texture));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+
+ GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, sz, 1, 0, GL_RGBA,
+ GL_UNSIGNED_INT_2_10_10_10_REV, data));
+ }
+ return texture;
+}
+
+//-----------------------------------------------------------------------------
+void dumpShaderLog(int shader)
+//-----------------------------------------------------------------------------
+{
+ int success;
+ GLchar infoLog[512];
+ GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
+ if (!success) {
+ glGetShaderInfoLog(shader, 512, NULL, infoLog);
+ ALOGI("Shader Failed to compile: %s\n", infoLog);
+ }
+}
+
+//-----------------------------------------------------------------------------
+GLuint engine_loadProgram(int vertexEntries, const char **vertex, int fragmentEntries,
+ const char **fragment)
+//-----------------------------------------------------------------------------
+{
+ GLuint progId = glCreateProgram();
+
+ int vertId = glCreateShader(GL_VERTEX_SHADER);
+ int fragId = glCreateShader(GL_FRAGMENT_SHADER);
+
+ GL(glShaderSource(vertId, vertexEntries, vertex, 0));
+ GL(glCompileShader(vertId));
+ dumpShaderLog(vertId);
+
+ GL(glShaderSource(fragId, fragmentEntries, fragment, 0));
+ GL(glCompileShader(fragId));
+ dumpShaderLog(fragId);
+
+ GL(glAttachShader(progId, vertId));
+ GL(glAttachShader(progId, fragId));
+
+ GL(glLinkProgram(progId));
+
+ GL(glDetachShader(progId, vertId));
+ GL(glDetachShader(progId, fragId));
+
+ GL(glDeleteShader(vertId));
+ GL(glDeleteShader(fragId));
+
+ return progId;
+}
+
+//-----------------------------------------------------------------------------
+void WaitOnNativeFence(int fd)
+//-----------------------------------------------------------------------------
+{
+ if (fd != -1) {
+ EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
+
+ EGLSyncKHR sync = eglCreateSyncKHR(eglDisplay, 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));
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+int CreateNativeFence()
+//-----------------------------------------------------------------------------
+{
+ int fd = -1;
+
+ EGLSyncKHR sync = eglCreateSyncKHR(eglDisplay, 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);
+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGE("%s - Failed to dup sync", __FUNCTION__);
+ }
+ EGL(eglDestroySyncKHR(eglDisplay, sync));
+ }
+
+ return fd;
+}
+
+//-----------------------------------------------------------------------------
+void engine_setDestination(int id, int x, int y, int w, int h)
+//-----------------------------------------------------------------------------
+{
+ GL(glBindFramebuffer(GL_FRAMEBUFFER, id));
+ GL(glViewport(x, y, w, h));
+}
+
+//-----------------------------------------------------------------------------
+void engine_setProgram(int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glUseProgram(id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_set2DInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glActiveTexture(GL_TEXTURE0 + binding));
+ GL(glBindTexture(GL_TEXTURE_2D, id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_set3DInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glActiveTexture(GL_TEXTURE0 + binding));
+ GL(glBindTexture(GL_TEXTURE_3D, id));
+}
+
+//-----------------------------------------------------------------------------
+void engine_setExternalInputBuffer(int binding, unsigned int id)
+//-----------------------------------------------------------------------------
+{
+ GL(glActiveTexture(GL_TEXTURE0 + binding));
+ GL(glBindTexture(0x8D65, id));
+}
+
+//-----------------------------------------------------------------------------
+int engine_blit(int srcFenceFd)
+//-----------------------------------------------------------------------------
+{
+ int fd = -1;
+ WaitOnNativeFence(srcFenceFd);
+ float fullscreen_vertices[]{0.0f, 2.0f, 0.0f, 0.0f, 2.0f, 0.0f};
+ GL(glEnableVertexAttribArray(0));
+ GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, fullscreen_vertices));
+ GL(glDrawArrays(GL_TRIANGLES, 0, 3));
+ fd = CreateNativeFence();
+ GL(glFlush());
+ return fd;
+}
+
+//-----------------------------------------------------------------------------
+void checkGlError(const char *file, int line)
+//-----------------------------------------------------------------------------
+{
+ for (GLint error = glGetError(); error; error = glGetError()) {
+ char *pError;
+ switch (error) {
+ case GL_NO_ERROR:
+ pError = (char *)"GL_NO_ERROR";
+ break;
+ case GL_INVALID_ENUM:
+ pError = (char *)"GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ pError = (char *)"GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ pError = (char *)"GL_INVALID_OPERATION";
+ break;
+ case GL_OUT_OF_MEMORY:
+ pError = (char *)"GL_OUT_OF_MEMORY";
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ pError = (char *)"GL_INVALID_FRAMEBUFFER_OPERATION";
+ break;
+
+ default:
+ ALOGE("glError (0x%x) %s:%d\n", error, file, line);
+ return;
+ }
+
+ ALOGE("glError (%s) %s:%d\n", pError, file, line);
+ return;
+ }
+ return;
+}
+
+//-----------------------------------------------------------------------------
+void checkEglError(const char *file, int line)
+//-----------------------------------------------------------------------------
+{
+ for (int i = 0; i < 5; i++) {
+ const EGLint error = eglGetError();
+ if (error == EGL_SUCCESS) {
+ break;
+ }
+
+ char *pError;
+ switch (error) {
+ case EGL_SUCCESS:
+ pError = (char *)"EGL_SUCCESS";
+ break;
+ case EGL_NOT_INITIALIZED:
+ pError = (char *)"EGL_NOT_INITIALIZED";
+ break;
+ case EGL_BAD_ACCESS:
+ pError = (char *)"EGL_BAD_ACCESS";
+ break;
+ case EGL_BAD_ALLOC:
+ pError = (char *)"EGL_BAD_ALLOC";
+ break;
+ case EGL_BAD_ATTRIBUTE:
+ pError = (char *)"EGL_BAD_ATTRIBUTE";
+ break;
+ case EGL_BAD_CONTEXT:
+ pError = (char *)"EGL_BAD_CONTEXT";
+ break;
+ case EGL_BAD_CONFIG:
+ pError = (char *)"EGL_BAD_CONFIG";
+ break;
+ case EGL_BAD_CURRENT_SURFACE:
+ pError = (char *)"EGL_BAD_CURRENT_SURFACE";
+ break;
+ case EGL_BAD_DISPLAY:
+ pError = (char *)"EGL_BAD_DISPLAY";
+ break;
+ case EGL_BAD_SURFACE:
+ pError = (char *)"EGL_BAD_SURFACE";
+ break;
+ case EGL_BAD_MATCH:
+ pError = (char *)"EGL_BAD_MATCH";
+ break;
+ case EGL_BAD_PARAMETER:
+ pError = (char *)"EGL_BAD_PARAMETER";
+ break;
+ case EGL_BAD_NATIVE_PIXMAP:
+ pError = (char *)"EGL_BAD_NATIVE_PIXMAP";
+ break;
+ case EGL_BAD_NATIVE_WINDOW:
+ pError = (char *)"EGL_BAD_NATIVE_WINDOW";
+ break;
+ case EGL_CONTEXT_LOST:
+ pError = (char *)"EGL_CONTEXT_LOST";
+ break;
+ default:
+ ALOGE("eglError (0x%x) %s:%d\n", error, file, line);
+ return;
+ }
+ ALOGE("eglError (%s) %s:%d\n", pError, file, line);
+ return;
+ }
+ return;
+}