upload android base code part4
This commit is contained in:
parent
b9e30e05b1
commit
78ea2404cd
23455 changed files with 5250148 additions and 0 deletions
|
@ -0,0 +1,28 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_VENDOR_MODULE := true
|
||||
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
|
||||
LOCAL_COPY_HEADERS := TonemapFactory.h Tonemapper.h
|
||||
LOCAL_VENDOR_MODULE := true
|
||||
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_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)
|
|
@ -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));
|
||||
}
|
|
@ -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__
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
|
@ -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 <utils/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;
|
||||
}
|
|
@ -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__
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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()
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
void* caller_context = engine_backup();
|
||||
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);
|
||||
// restore the caller context
|
||||
engine_bind(caller_context);
|
||||
engine_free_backup(caller_context);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
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);
|
||||
|
||||
void* caller_context = engine_backup();
|
||||
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);
|
||||
|
||||
// restore the caller context
|
||||
engine_bind(caller_context);
|
||||
engine_free_backup(caller_context);
|
||||
|
||||
return tonemapper;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
void* caller_context = engine_backup();
|
||||
// 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);
|
||||
|
||||
// restore the caller context
|
||||
engine_bind(caller_context);
|
||||
engine_free_backup(caller_context);
|
||||
|
||||
|
||||
return fenceFD;
|
||||
}
|
|
@ -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__
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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_backup();
|
||||
void engine_free_backup(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__
|
|
@ -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";
|
|
@ -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";
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* 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 <utils/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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// store the current context(caller)
|
||||
void* engine_backup()
|
||||
{
|
||||
EngineContext* callerContext = new EngineContext();
|
||||
// store the previous display/context
|
||||
callerContext->eglDisplay = eglGetCurrentDisplay();
|
||||
callerContext->eglContext = eglGetCurrentContext();
|
||||
callerContext->eglSurface = eglGetCurrentSurface(EGL_DRAW);
|
||||
|
||||
return (void*)callerContext;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// frees the backed up caller context
|
||||
void engine_free_backup(void* context)
|
||||
{
|
||||
EngineContext* callerContext = (EngineContext*)(context);
|
||||
|
||||
delete callerContext;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
|
@ -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__
|
|
@ -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";
|
Loading…
Add table
Add a link
Reference in a new issue