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/Android.mk b/Android.mk
index 60a48f5..6eef2fc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,7 +3,7 @@
ifneq ($(TARGET_IS_HEADLESS), true)
display-hals += libcopybit liblight libmemtrack hdmi_cec \
- $(sdm-libs)/hwc $(sdm-libs)/hwc2
+ $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper
endif
ifneq ($(TARGET_USES_GRALLOC1), true)
diff --git a/common.mk b/common.mk
index d44a664..6476dfd 100644
--- a/common.mk
+++ b/common.mk
@@ -17,6 +17,7 @@
common_includes := $(display_top)/libqdutils
common_includes += $(display_top)/libqservice
+common_includes += $(display_top)/gpu_tonemapper
ifneq ($(TARGET_IS_HEADLESS), true)
common_includes += $(display_top)/libcopybit
endif
diff --git a/gpu_tonemapper/Android.mk b/gpu_tonemapper/Android.mk
new file mode 100644
index 0000000..9ae3840
--- /dev/null
+++ b/gpu_tonemapper/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
+LOCAL_COPY_HEADERS := TonemapFactory.h Tonemapper.h
+LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libui libutils liblog
+include $(BUILD_COPY_HEADERS)
+
+LOCAL_MODULE := libgpu_tonemapper
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(TARGET_OUT_HEADERS)/qcom/display/
+
+LOCAL_CFLAGS := -Wno-missing-field-initializers -Wall \
+ -Wno-unused-parameter -std=c++11 -DLOG_TAG=\"GPU_TONEMAPPER\"
+
+LOCAL_SRC_FILES := TonemapFactory.cpp \
+ glengine.cpp \
+ EGLImageBuffer.cpp \
+ EGLImageWrapper.cpp \
+ Tonemapper.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/gpu_tonemapper/EGLImageBuffer.cpp b/gpu_tonemapper/EGLImageBuffer.cpp
new file mode 100644
index 0000000..e64e16f
--- /dev/null
+++ b/gpu_tonemapper/EGLImageBuffer.cpp
@@ -0,0 +1,155 @@
+/*
+ * 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 "EGLImageBuffer.h"
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <map>
+#include "EGLImageWrapper.h"
+#include "glengine.h"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+//-----------------------------------------------------------------------------
+EGLImageKHR create_eglImage(android::sp<android::GraphicBuffer> graphicBuffer)
+//-----------------------------------------------------------------------------
+{
+ bool isProtected = (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+ EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ isProtected ? EGL_TRUE : EGL_NONE, EGL_NONE};
+
+ EGLImageKHR eglImage = eglCreateImageKHR(
+ eglGetCurrentDisplay(), (EGLContext)EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)(graphicBuffer->getNativeBuffer()), attrs);
+
+ return eglImage;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer::EGLImageBuffer(android::sp<android::GraphicBuffer> graphicBuffer)
+//-----------------------------------------------------------------------------
+{
+ // this->graphicBuffer = graphicBuffer;
+ this->eglImageID = create_eglImage(graphicBuffer);
+ this->width = graphicBuffer->getWidth();
+ this->height = graphicBuffer->getHeight();
+
+ textureID = 0;
+ renderbufferID = 0;
+ framebufferID = 0;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer::~EGLImageBuffer()
+//-----------------------------------------------------------------------------
+{
+ if (textureID != 0) {
+ GL(glDeleteTextures(1, &textureID));
+ textureID = 0;
+ }
+
+ if (renderbufferID != 0) {
+ GL(glDeleteRenderbuffers(1, &renderbufferID));
+ renderbufferID = 0;
+ }
+
+ if (framebufferID != 0) {
+ GL(glDeleteFramebuffers(1, &framebufferID));
+ framebufferID = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+int EGLImageBuffer::getWidth()
+//-----------------------------------------------------------------------------
+{
+ return width;
+}
+
+//-----------------------------------------------------------------------------
+int EGLImageBuffer::getHeight()
+//-----------------------------------------------------------------------------
+{
+ return height;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int EGLImageBuffer::getTexture()
+//-----------------------------------------------------------------------------
+{
+ if (textureID == 0) {
+ bindAsTexture();
+ }
+
+ return textureID;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int EGLImageBuffer::getFramebuffer()
+//-----------------------------------------------------------------------------
+{
+ if (framebufferID == 0) {
+ bindAsFramebuffer();
+ }
+
+ return framebufferID;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageBuffer::bindAsTexture()
+//-----------------------------------------------------------------------------
+{
+ if (textureID == 0) {
+ GL(glGenTextures(1, &textureID));
+ int target = 0x8D65;
+ GL(glBindTexture(target, textureID));
+ GL(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GL(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+
+ GL(glEGLImageTargetTexture2DOES(0x8D65, eglImageID));
+ }
+
+ GL(glBindTexture(0x8D65, textureID));
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageBuffer::bindAsFramebuffer()
+//-----------------------------------------------------------------------------
+{
+ if (renderbufferID == 0) {
+ GL(glGenFramebuffers(1, &framebufferID));
+ GL(glGenRenderbuffers(1, &renderbufferID));
+
+ GL(glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID));
+ GL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, eglImageID));
+
+ GL(glBindFramebuffer(GL_FRAMEBUFFER, framebufferID));
+ GL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ renderbufferID));
+ GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (result != GL_FRAMEBUFFER_COMPLETE) {
+ ALOGI("%s Framebuffer Invalid***************", __FUNCTION__);
+ }
+ }
+
+ GL(glBindFramebuffer(GL_FRAMEBUFFER, framebufferID));
+}
diff --git a/gpu_tonemapper/EGLImageBuffer.h b/gpu_tonemapper/EGLImageBuffer.h
new file mode 100644
index 0000000..23af573
--- /dev/null
+++ b/gpu_tonemapper/EGLImageBuffer.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef __EGLIMAGE_BUFFER_H__
+#define __EGLIMAGE_BUFFER_H__
+
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+#include "engine.h"
+
+class EGLImageBuffer {
+ // android::sp<android::GraphicBuffer> graphicBuffer;
+ void *eglImageID;
+ int width;
+ int height;
+ uint textureID;
+ uint renderbufferID;
+ uint framebufferID;
+
+ public:
+ int getWidth();
+ int getHeight();
+ EGLImageBuffer(android::sp<android::GraphicBuffer>);
+ unsigned int getTexture();
+ unsigned int getFramebuffer();
+ void bindAsTexture();
+ void bindAsFramebuffer();
+ ~EGLImageBuffer();
+ static EGLImageBuffer *from(const private_handle_t *src);
+ static void clear();
+};
+
+#endif //__EGLIMAGE_BUFFER_H__
\ No newline at end of file
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
new file mode 100644
index 0000000..eb0a2ca
--- /dev/null
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "EGLImageWrapper.h"
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+#include <ui/GraphicBuffer.h>
+
+std::map<int, EGLImageBuffer *> EGLImageWrapper::eglImageBufferMap;
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
+//-----------------------------------------------------------------------------
+{
+ const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
+
+ EGLImageBuffer *result = 0;
+ std::map<int, EGLImageBuffer *>::iterator it = eglImageBufferMap.find(src->fd);
+ if (it == eglImageBufferMap.end()) {
+ 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;
+ }
+
+ android::sp<android::GraphicBuffer> graphicBuffer =
+ new android::GraphicBuffer(src->width, src->height, src->format, flags,
+ src->width /*src->stride*/, native_handle, false);
+
+ result = new EGLImageBuffer(graphicBuffer);
+
+ eglImageBufferMap[src->fd] = result;
+ } else {
+ result = it->second;
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::destroy()
+//-----------------------------------------------------------------------------
+{
+ std::map<int, EGLImageBuffer *>::iterator it = eglImageBufferMap.begin();
+ for (; it != eglImageBufferMap.end(); it++) {
+ delete it->second;
+ }
+ eglImageBufferMap.clear();
+}
\ No newline at end of file
diff --git a/gpu_tonemapper/EGLImageWrapper.h b/gpu_tonemapper/EGLImageWrapper.h
new file mode 100644
index 0000000..d7fc84b
--- /dev/null
+++ b/gpu_tonemapper/EGLImageWrapper.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef __TONEMAPPER_EGLIMAGEWRAPPER_H__
+#define __TONEMAPPER_EGLIMAGEWRAPPER_H__
+
+#include <map>
+#include "EGLImageBuffer.h"
+
+class EGLImageWrapper {
+ static std::map<int, EGLImageBuffer *> eglImageBufferMap;
+
+ public:
+ static EGLImageBuffer *wrap(const void *pvt_handle);
+ static void destroy();
+};
+
+#endif //__TONEMAPPER_EGLIMAGEWRAPPER_H__
\ No newline at end of file
diff --git a/gpu_tonemapper/TonemapFactory.cpp b/gpu_tonemapper/TonemapFactory.cpp
new file mode 100644
index 0000000..81e9f7f
--- /dev/null
+++ b/gpu_tonemapper/TonemapFactory.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "TonemapFactory.h"
+#include <utils/Log.h>
+#include "EGLImageWrapper.h"
+#include "Tonemapper.h"
+#include "engine.h"
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+ 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);
+
+ return tonemapper;
+}
+
+//------------------------------------------
+void TonemapperFactory_Destroy()
+//------------------------------------------
+{
+ // clear EGLImage mappings
+ EGLImageWrapper::destroy();
+ // shutdown the engine
+ engine_shutdown();
+}
diff --git a/gpu_tonemapper/TonemapFactory.h b/gpu_tonemapper/TonemapFactory.h
new file mode 100644
index 0000000..1004170
--- /dev/null
+++ b/gpu_tonemapper/TonemapFactory.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef __TONEMAPPER_TONEMAPPERFACTORY_H__
+#define __TONEMAPPER_TONEMAPPERFACTORY_H__
+
+#include "Tonemapper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// returns an instance of Tonemapper
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+ void *lutXform, int lutXformSize);
+
+// destroy tonemap session
+void TonemapperFactory_Destroy();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TONEMAPPER_TONEMAPPERFACTORY_H__
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
new file mode 100644
index 0000000..957c133
--- /dev/null
+++ b/gpu_tonemapper/Tonemapper.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <utils/Log.h>
+
+#include "EGLImageWrapper.h"
+#include "Tonemapper.h"
+#include "engine.h"
+#include "forward_tonemap.inl"
+#include "fullscreen_vertex_shader.inl"
+#include "rgba_inverse_tonemap.inl"
+
+//-----------------------------------------------------------------------------
+Tonemapper::Tonemapper()
+//-----------------------------------------------------------------------------
+{
+ tonemapTexture = 0;
+ lutXformTexture = 0;
+ programID = 0;
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper::~Tonemapper()
+//-----------------------------------------------------------------------------
+{
+ engine_deleteInputBuffer(tonemapTexture);
+ engine_deleteInputBuffer(lutXformTexture);
+ engine_deleteProgram(programID);
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
+ int lutXformSize)
+//-----------------------------------------------------------------------------
+{
+ if (colorMapSize <= 0) {
+ ALOGE("Invalid Color Map size = %d", colorMapSize);
+ return NULL;
+ }
+ engine_bind();
+
+ // build new tonemapper
+ Tonemapper *tonemapper = new Tonemapper();
+ // load the 3d lut
+ tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
+ // load the non-uniform xform
+ tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
+ bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
+
+ // create the program
+ const char *fragmentShaders[3];
+ int fragmentShaderCount = 0;
+ const char *version = "#version 300 es\n";
+ const char *define = "#define USE_NONUNIFORM_SAMPLING\n";
+
+ fragmentShaders[fragmentShaderCount++] = version;
+
+ // non-uniform sampling
+ if (bUseXform) {
+ fragmentShaders[fragmentShaderCount++] = define;
+ }
+
+ if (type == TONEMAP_INVERSE) { // inverse tonemapping
+ fragmentShaders[fragmentShaderCount++] = rgba_inverse_tonemap_shader;
+ } else { // forward tonemapping
+ fragmentShaders[fragmentShaderCount++] = forward_tonemap_shader;
+ }
+
+ tonemapper->programID =
+ engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
+
+ return tonemapper;
+}
+
+//-----------------------------------------------------------------------------
+int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
+//-----------------------------------------------------------------------------
+{
+ // make current
+ engine_bind();
+
+ // create eglimages if required
+ EGLImageBuffer *dst_buffer = EGLImageWrapper::wrap(dst);
+ EGLImageBuffer *src_buffer = EGLImageWrapper::wrap(src);
+
+ // bind the program
+ engine_setProgram(programID);
+
+ // set destination
+ engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
+ dst_buffer->getHeight());
+ // set source
+ engine_setExternalInputBuffer(0, src_buffer->getTexture());
+ // set 3d lut
+ engine_set3DInputBuffer(1, tonemapTexture);
+ // set non-uniform xform
+ engine_set2DInputBuffer(2, lutXformTexture);
+
+ // perform
+ int fenceFD = engine_blit(srcFenceFd);
+
+ return fenceFD;
+}
diff --git a/gpu_tonemapper/Tonemapper.h b/gpu_tonemapper/Tonemapper.h
new file mode 100644
index 0000000..9c41670
--- /dev/null
+++ b/gpu_tonemapper/Tonemapper.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef __TONEMAPPER_TONEMAP_H__
+#define __TONEMAPPER_TONEMAP_H__
+
+#define TONEMAP_FORWARD 0
+#define TONEMAP_INVERSE 1
+
+class Tonemapper {
+ private:
+ unsigned int tonemapTexture;
+ unsigned int lutXformTexture;
+ unsigned int programID;
+ Tonemapper();
+
+ public:
+ ~Tonemapper();
+ static Tonemapper *build(int type, void *colorMap, int colorMapSize, void *lutXform,
+ int lutXformSize);
+ int blit(const void *dst, const void *src, int srcFenceFd);
+};
+
+#endif //__TONEMAPPER_TONEMAP_H__
diff --git a/gpu_tonemapper/engine.h b/gpu_tonemapper/engine.h
new file mode 100644
index 0000000..5635ee3
--- /dev/null
+++ b/gpu_tonemapper/engine.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef __TONEMAPPER_ENGINE_H__
+#define __TONEMAPPER_ENGINE_H__
+
+bool engine_initialize();
+void engine_bind();
+void engine_shutdown();
+
+unsigned int engine_loadProgram(int, const char **, int, const char **);
+void engine_setProgram(int);
+void engine_deleteProgram(unsigned int);
+
+unsigned int engine_load3DTexture(void *data, int sz, int format);
+unsigned int engine_load1DTexture(void *xform, int xformSize, int format);
+void engine_deleteInputBuffer(unsigned int);
+
+void engine_set2DInputBuffer(int binding, unsigned int textureID);
+void engine_set3DInputBuffer(int binding, unsigned int textureID);
+void engine_setExternalInputBuffer(int binding, unsigned int textureID);
+void engine_setDestination(int id, int x, int y, int w, int h);
+
+int engine_blit(int);
+
+#endif //__TONEMAPPER_ENGINE_H__
\ No newline at end of file
diff --git a/gpu_tonemapper/forward_tonemap.inl b/gpu_tonemapper/forward_tonemap.inl
new file mode 100644
index 0000000..a008949
--- /dev/null
+++ b/gpu_tonemapper/forward_tonemap.inl
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+const char* forward_tonemap_shader = ""
+ "#extension GL_OES_EGL_image_external_essl3 : require \n"
+ "precision highp float; \n"
+ "precision highp sampler2D; \n"
+ "layout(binding = 0) uniform samplerExternalOES externalTexture; \n"
+ "layout(binding = 1) uniform sampler3D tonemapper; \n"
+ "layout(binding = 2) uniform sampler2D xform; \n"
+ "in vec2 uv; \n"
+ "out vec4 fs_color; \n"
+ "void main() \n"
+ "{ \n"
+ "vec4 rgb = texture(externalTexture, uv); \n"
+ "#if defined(USE_NONUNIFORM_SAMPLING) \n"
+ "float r = texture(xform, vec2(r, 0.0f)).r; \n"
+ "float g = texture(xform, vec2(g, 0.0f)).g; \n"
+ "float b = texture(xform, vec2(b, 0.0f)).b; \n"
+ "#else \n"
+ "float r = rgb.r; \n"
+ "float g = rgb.g; \n"
+ "float b = rgb.b; \n"
+ "#endif \n"
+ "fs_color.rgb = texture(tonemapper, vec3(r, g, b)).rgb; \n"
+ "} \n";
diff --git a/gpu_tonemapper/fullscreen_vertex_shader.inl b/gpu_tonemapper/fullscreen_vertex_shader.inl
new file mode 100644
index 0000000..9a70c2b
--- /dev/null
+++ b/gpu_tonemapper/fullscreen_vertex_shader.inl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+const char* fullscreen_vertex_shader = " "
+"#version 300 es \n"
+"precision highp float; \n"
+"layout(location = 0) in vec2 iUV; \n"
+"out vec2 uv; \n"
+"void main() \n"
+"{ \n"
+" vec2 positions[3]; \n"
+" positions[0] = vec2(-1.0f, 3.0f); \n"
+" positions[1] = vec2(-1.0f, -1.0f); \n"
+" positions[2] = vec2(3.0f, -1.0f); \n"
+" vec2 uvs[3]; \n"
+" uvs[0] = vec2(0.0f, -1.0f); \n"
+" uvs[1] = vec2(0.0f, 1.0f); \n"
+" uvs[2] = vec2(2.0f, 1.0f); \n"
+" gl_Position = vec4(positions[gl_VertexID], -1.0f, 1.0f); \n"
+" uv = uvs[gl_VertexID]; \n"
+"} \n";
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;
+}
diff --git a/gpu_tonemapper/glengine.h b/gpu_tonemapper/glengine.h
new file mode 100644
index 0000000..c5b166c
--- /dev/null
+++ b/gpu_tonemapper/glengine.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef __TONEMAPPER_GLENGINE_H__
+#define __TONEMAPPER_GLENGINE_H__
+#include <EGL/egl.h>
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/eglext.h>
+#include <GLES3/gl31.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GLES2/gl2ext.h>
+#include <GLES3/gl3ext.h>
+
+#if defined(CHECK_GL_ERRORS)
+#define GL(func) func;
+#define EGL(func) func;
+#else
+#define GL(func) \
+ func; \
+ checkGlError(__FILE__, __LINE__);
+#define EGL(func) \
+ func; \
+ checkEglError(__FILE__, __LINE__);
+#endif
+
+void checkGlError(const char *file, int line);
+void checkEglError(const char *file, int line);
+
+#endif //__TONEMAPPER_GLENGINE_H__
\ No newline at end of file
diff --git a/gpu_tonemapper/rgba_inverse_tonemap.inl b/gpu_tonemapper/rgba_inverse_tonemap.inl
new file mode 100644
index 0000000..399e2f8
--- /dev/null
+++ b/gpu_tonemapper/rgba_inverse_tonemap.inl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+const char* rgba_inverse_tonemap_shader = ""
+ "#extension GL_OES_EGL_image_external_essl3 : require \n"
+ "precision highp float; \n"
+ "precision highp sampler2D; \n"
+ "layout(binding = 0) uniform samplerExternalOES externalTexture; \n"
+ "layout(binding = 1) uniform sampler3D tonemapper; \n"
+ "layout(binding = 2) uniform sampler2D xform; \n"
+ "in vec2 uv; \n"
+ "out vec4 fs_color; \n"
+ "void main() \n"
+ "{ \n"
+ "vec2 flipped = uv; \n"
+ "flipped.y = 1.0 - flipped.y; \n"
+ "flipped.x = flipped.x; \n"
+ "vec4 rgb_premulalpha = texture(externalTexture, flipped); \n"
+ "fs_color = rgb_premulalpha; \n"
+ "if( rgb_premulalpha.a > 0.0 ) { \n"
+ "vec3 rgb = rgb_premulalpha.rgb/rgb_premulalpha.a; \n"
+ "#if defined(USE_NONUNIFORM_SAMPLING) \n"
+ "float r = texture(xform, vec2(rgb.r, 0.0f)).r; \n"
+ "float g = texture(xform, vec2(rgb.g, 0.0f)).g; \n"
+ "float b = texture(xform, vec2(rgb.b, 0.0f)).b; \n"
+ "#else \n"
+ "float r = rgb.r; \n"
+ "float g = rgb.g; \n"
+ "float b = rgb.b; \n"
+ "#endif \n"
+ "fs_color.rgb = texture(tonemapper, vec3(r, g, b)).rgb * rgb_premulalpha.a; \n"
+ "fs_color.a = rgb_premulalpha.a; \n"
+ "} \n"
+ "} \n";