/* * 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 #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; }