display: msm8909w caf release LW.BR.4.0-00800-8x09w.0 for SD2100.
MSM8909W display HAL code copied from CAF release LW.BR.4.0-00800-8x09w.0.
Bug: 79356346
Test: build
Change-Id: Ie801976595c8ed9164b0d91737f5daf40764d8a6
Signed-off-by: Ben Fennema <[email protected]>
diff --git a/msm8909/gpu_tonemapper/Android.mk b/msm8909/gpu_tonemapper/Android.mk
new file mode 100644
index 0000000..77ecc4a
--- /dev/null
+++ b/msm8909/gpu_tonemapper/Android.mk
@@ -0,0 +1,27 @@
+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
+include $(BUILD_COPY_HEADERS)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libgpu_tonemapper
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(TARGET_OUT_HEADERS)/qcom/display/
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libGLESv3 libui libutils liblog
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+
+LOCAL_CFLAGS := $(version_flag) -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/msm8909/gpu_tonemapper/EGLImageBuffer.cpp b/msm8909/gpu_tonemapper/EGLImageBuffer.cpp
new file mode 100644
index 0000000..eeb0273
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageBuffer.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016-2017, 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"
+
+//-----------------------------------------------------------------------------
+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;
+ }
+
+ // Delete the eglImage
+ if (eglImageID != 0)
+ {
+ eglDestroyImageKHR(eglGetCurrentDisplay(), eglImageID);
+ eglImageID = 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/msm8909/gpu_tonemapper/EGLImageBuffer.h b/msm8909/gpu_tonemapper/EGLImageBuffer.h
new file mode 100644
index 0000000..23af573
--- /dev/null
+++ b/msm8909/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/msm8909/gpu_tonemapper/EGLImageWrapper.cpp b/msm8909/gpu_tonemapper/EGLImageWrapper.cpp
new file mode 100644
index 0000000..dfc16d8
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageWrapper.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016-2017, 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>
+#include <fcntl.h>
+#include <linux/msm_ion.h>
+
+//-----------------------------------------------------------------------------
+void free_ion_cookie(int ion_fd, int cookie)
+//-----------------------------------------------------------------------------
+{
+ if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
+ } else {
+ ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
+ }
+}
+
+//-----------------------------------------------------------------------------
+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;
+ }
+
+ android::sp<android::GraphicBuffer> graphicBuffer =
+ new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
+#ifndef __NOUGAT__
+ 1, // Layer count
+#endif
+ flags, src->width /*src->stride*/,
+ native_handle, false);
+
+ result = new EGLImageBuffer(graphicBuffer);
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
+//-----------------------------------------------------------------------------
+{
+ 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/msm8909/gpu_tonemapper/EGLImageWrapper.h b/msm8909/gpu_tonemapper/EGLImageWrapper.h
new file mode 100644
index 0000000..e9a4d68
--- /dev/null
+++ b/msm8909/gpu_tonemapper/EGLImageWrapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, 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 <utils/LruCache.h>
+#include "EGLImageBuffer.h"
+
+class EGLImageWrapper {
+ private:
+ class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*>
+ {
+ private:
+ int ion_fd;
+ public:
+ DeleteEGLImageCallback(int ion_fd);
+ void operator()(int& ion_cookie, EGLImageBuffer*& eglImage);
+ };
+
+ 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/msm8909/gpu_tonemapper/TonemapFactory.cpp b/msm8909/gpu_tonemapper/TonemapFactory.cpp
new file mode 100644
index 0000000..db4b8be
--- /dev/null
+++ b/msm8909/gpu_tonemapper/TonemapFactory.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2017, 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 <log/log.h>
+#include "Tonemapper.h"
+#include "engine.h"
+
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+Tonemapper *TonemapperFactory_GetInstance(int type, void *colorMap, int colorMapSize,
+ void *lutXform, int lutXformSize, bool isSecure)
+//----------------------------------------------------------------------------------------------------------------------------------------------------------
+{
+ // build the tonemapper
+ Tonemapper *tonemapper = Tonemapper::build(type, colorMap, colorMapSize, lutXform, lutXformSize, isSecure);
+
+ return tonemapper;
+}
diff --git a/msm8909/gpu_tonemapper/TonemapFactory.h b/msm8909/gpu_tonemapper/TonemapFactory.h
new file mode 100644
index 0000000..17cad40
--- /dev/null
+++ b/msm8909/gpu_tonemapper/TonemapFactory.h
@@ -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.
+ */
+
+#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, bool isSecure);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__TONEMAPPER_TONEMAPPERFACTORY_H__
diff --git a/msm8909/gpu_tonemapper/Tonemapper.cpp b/msm8909/gpu_tonemapper/Tonemapper.cpp
new file mode 100644
index 0000000..811e091
--- /dev/null
+++ b/msm8909/gpu_tonemapper/Tonemapper.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016-2017, 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;
+ eglImageWrapper = new EGLImageWrapper();
+
+ lutXformScaleOffset[0] = 1.0f;
+ lutXformScaleOffset[1] = 0.0f;
+
+ tonemapScaleOffset[0] = 1.0f;
+ tonemapScaleOffset[1] = 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper::~Tonemapper()
+//-----------------------------------------------------------------------------
+{
+ engine_bind(engineContext);
+ engine_deleteInputBuffer(tonemapTexture);
+ engine_deleteInputBuffer(lutXformTexture);
+ engine_deleteProgram(programID);
+
+ // clear EGLImage mappings
+ if (eglImageWrapper != 0) {
+ delete eglImageWrapper;
+ eglImageWrapper = 0;
+ }
+
+ engine_shutdown(engineContext);
+}
+
+//-----------------------------------------------------------------------------
+Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
+ int lutXformSize, bool isSecure)
+//-----------------------------------------------------------------------------
+{
+ if (colorMapSize <= 0) {
+ ALOGE("Invalid Color Map size = %d", colorMapSize);
+ return NULL;
+ }
+
+ // build new tonemapper
+ Tonemapper *tonemapper = new Tonemapper();
+
+ tonemapper->engineContext = engine_initialize(isSecure);
+
+ engine_bind(tonemapper->engineContext);
+
+ // load the 3d lut
+ tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
+ tonemapper->tonemapScaleOffset[0] = ((float)(colorMapSize-1))/((float)(colorMapSize));
+ tonemapper->tonemapScaleOffset[1] = 1.0f/(2.0f*colorMapSize);
+
+ // load the non-uniform xform
+ tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
+ bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
+ if( bUseXform )
+ {
+ tonemapper->lutXformScaleOffset[0] = ((float)(lutXformSize-1))/((float)(lutXformSize));
+ tonemapper->lutXformScaleOffset[1] = 1.0f/(2.0f*lutXformSize);
+ }
+
+ // 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(engineContext);
+
+ // create eglimages if required
+ EGLImageBuffer *dst_buffer = eglImageWrapper->wrap(dst);
+ EGLImageBuffer *src_buffer = eglImageWrapper->wrap(src);
+
+ // bind the program
+ engine_setProgram(programID);
+
+ engine_setData2f(3, tonemapScaleOffset);
+ bool bUseXform = (lutXformTexture != 0);
+ if( bUseXform )
+ {
+ engine_setData2f(4, lutXformScaleOffset);
+ }
+
+ // 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/msm8909/gpu_tonemapper/Tonemapper.h b/msm8909/gpu_tonemapper/Tonemapper.h
new file mode 100644
index 0000000..707cdfe
--- /dev/null
+++ b/msm8909/gpu_tonemapper/Tonemapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, 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
+
+#include "EGLImageWrapper.h"
+#include "engine.h"
+
+class Tonemapper {
+ private:
+ void* engineContext;
+ unsigned int tonemapTexture;
+ unsigned int lutXformTexture;
+ unsigned int programID;
+ float lutXformScaleOffset[2];
+ float tonemapScaleOffset[2];
+ EGLImageWrapper* eglImageWrapper;
+ Tonemapper();
+
+ public:
+ ~Tonemapper();
+ static Tonemapper *build(int type, void *colorMap, int colorMapSize, void *lutXform,
+ int lutXformSize, bool isSecure);
+ int blit(const void *dst, const void *src, int srcFenceFd);
+};
+
+#endif //__TONEMAPPER_TONEMAP_H__
diff --git a/msm8909/gpu_tonemapper/engine.h b/msm8909/gpu_tonemapper/engine.h
new file mode 100644
index 0000000..8fb9452
--- /dev/null
+++ b/msm8909/gpu_tonemapper/engine.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016-2017, 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__
+
+void* engine_initialize(bool isSecure);
+void engine_bind(void*);
+void engine_shutdown(void*);
+
+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);
+void engine_setData2f(int loc, float* data);
+
+int engine_blit(int);
+
+#endif //__TONEMAPPER_ENGINE_H__
diff --git a/msm8909/gpu_tonemapper/forward_tonemap.inl b/msm8909/gpu_tonemapper/forward_tonemap.inl
new file mode 100644
index 0000000..0d89a9e
--- /dev/null
+++ b/msm8909/gpu_tonemapper/forward_tonemap.inl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016-2017, 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"
+ "layout(location = 3) uniform vec2 tSO; \n"
+ "#ifdef USE_NONUNIFORM_SAMPLING \n"
+ "layout(location = 4) uniform vec2 xSO; \n"
+ "#endif \n"
+ "in vec2 uv; \n"
+ "out vec4 fs_color; \n"
+ " \n"
+ "vec3 ScaleOffset(in vec3 samplePt, in vec2 so) \n"
+ "{ \n"
+ " vec3 adjPt = so.x * samplePt + so.y; \n"
+ " return adjPt; \n"
+ "} \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ "vec2 flipped = vec2(uv.x, 1.0f - uv.y); \n"
+ "vec4 rgb = texture(externalTexture, flipped); \n"
+ "#ifdef USE_NONUNIFORM_SAMPLING \n"
+ "vec3 adj = ScaleOffset(rgb.xyz, xSO); \n"
+ "float r = texture(xform, vec2(adj.r, 0.5f)).r; \n"
+ "float g = texture(xform, vec2(adj.g, 0.5f)).g; \n"
+ "float b = texture(xform, vec2(adj.b, 0.5f)).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, ScaleOffset(vec3(r, g, b), tSO)).rgb; \n"
+ "} \n";
diff --git a/msm8909/gpu_tonemapper/fullscreen_vertex_shader.inl b/msm8909/gpu_tonemapper/fullscreen_vertex_shader.inl
new file mode 100644
index 0000000..9a70c2b
--- /dev/null
+++ b/msm8909/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/msm8909/gpu_tonemapper/glengine.cpp b/msm8909/gpu_tonemapper/glengine.cpp
new file mode 100644
index 0000000..35e1932
--- /dev/null
+++ b/msm8909/gpu_tonemapper/glengine.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2016-2017, 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 <log/log.h>
+#include "engine.h"
+
+void checkGlError(const char *, int);
+void checkEglError(const char *, int);
+
+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* context)
+//-----------------------------------------------------------------------------
+{
+ EngineContext* engineContext = (EngineContext*)(context);
+ EGL(eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext));
+}
+
+//-----------------------------------------------------------------------------
+// initialize GL
+//
+void* engine_initialize(bool isSecure)
+//-----------------------------------------------------------------------------
+{
+ EngineContext* engineContext = new EngineContext();
+
+ // display
+ engineContext->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ EGL(eglBindAPI(EGL_OPENGL_ES_API));
+
+ // initialize
+ EGL(eglInitialize(engineContext->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(engineContext->eglDisplay, eglConfigAttribList, &eglConfig, 1, &numConfig));
+
+ // context
+ EGLint eglContextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
+ isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ isSecure ? EGL_TRUE : EGL_NONE,
+ EGL_NONE};
+ engineContext->eglContext = eglCreateContext(engineContext->eglDisplay, eglConfig, NULL, eglContextAttribList);
+
+ // surface
+ EGLint eglSurfaceAttribList[] = {EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ isSecure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+ isSecure ? EGL_TRUE : EGL_NONE,
+ EGL_NONE};
+ engineContext->eglSurface = eglCreatePbufferSurface(engineContext->eglDisplay, eglConfig, eglSurfaceAttribList);
+
+ eglMakeCurrent(engineContext->eglDisplay, engineContext->eglSurface, engineContext->eglSurface, engineContext->eglContext);
+
+ ALOGI("In %s context = %p", __FUNCTION__, (void *)(engineContext->eglContext));
+
+ return (void*)(engineContext);
+}
+
+//-----------------------------------------------------------------------------
+// Shutdown.
+void engine_shutdown(void* context)
+//-----------------------------------------------------------------------------
+{
+ 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;
+}
+
+//-----------------------------------------------------------------------------
+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));
+ }
+}
+
+//-----------------------------------------------------------------------------
+void engine_setData2f(int location, float* data)
+//-----------------------------------------------------------------------------
+{
+ GL(glUniform2f(location, data[0], data[1]));
+}
+
+//-----------------------------------------------------------------------------
+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 = 0;
+ 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(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(eglGetCurrentDisplay(), sync, 0));
+ EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+int CreateNativeFence()
+//-----------------------------------------------------------------------------
+{
+ int fd = -1;
+
+ 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(eglGetCurrentDisplay(), sync);
+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGE("%s - Failed to dup sync", __FUNCTION__);
+ }
+ EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), 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/msm8909/gpu_tonemapper/glengine.h b/msm8909/gpu_tonemapper/glengine.h
new file mode 100644
index 0000000..f6aeec8
--- /dev/null
+++ b/msm8909/gpu_tonemapper/glengine.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+void checkGlError(const char *file, int line);
+void checkEglError(const char *file, int line);
+
+#endif //__TONEMAPPER_GLENGINE_H__
diff --git a/msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl b/msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl
new file mode 100644
index 0000000..2865fbe
--- /dev/null
+++ b/msm8909/gpu_tonemapper/rgba_inverse_tonemap.inl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016-2017, 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"
+ "layout(location = 3) uniform vec2 tSO; \n"
+ "#if defined(USE_NONUNIFORM_SAMPLING) \n"
+ "layout(location = 4) uniform vec2 xSO; \n"
+ "#endif \n"
+ "in vec2 uv; \n"
+ "out vec4 fs_color; \n"
+ " \n"
+ "vec3 ScaleOffset(in vec3 samplePt, in vec2 so) \n"
+ "{ \n"
+ " vec3 adjPt = so.x * samplePt + so.y; \n"
+ " return adjPt; \n"
+ "} \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ "vec2 flipped = vec2(uv.x, 1.0f - uv.y); \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"
+ "vec3 adj = ScaleOffset(rgb.xyz, xSO); \n"
+ "float r = texture(xform, vec2(adj.r, 0.5f)).r; \n"
+ "float g = texture(xform, vec2(adj.g, 0.5f)).g; \n"
+ "float b = texture(xform, vec2(adj.b, 0.5f)).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, ScaleOffset(vec3(r, g, b), tSO)).rgb * rgb_premulalpha.a; \n"
+ "fs_color.a = rgb_premulalpha.a; \n"
+ "} \n"
+ "} \n";