Home | History | Annotate | Download | only in gpu_tonemapper
      1 /*
      2  * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
      3  * Not a Contribution.
      4  *
      5  * Copyright 2015 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  */
     19 #include <utils/Log.h>
     20 
     21 #include "EGLImageWrapper.h"
     22 #include "Tonemapper.h"
     23 #include "engine.h"
     24 #include "forward_tonemap.inl"
     25 #include "fullscreen_vertex_shader.inl"
     26 #include "rgba_inverse_tonemap.inl"
     27 
     28 //-----------------------------------------------------------------------------
     29 Tonemapper::Tonemapper()
     30 //-----------------------------------------------------------------------------
     31 {
     32   tonemapTexture = 0;
     33   lutXformTexture = 0;
     34   programID = 0;
     35   eglImageWrapper = new EGLImageWrapper();
     36 
     37   lutXformScaleOffset[0] = 1.0f;
     38   lutXformScaleOffset[1] = 0.0f;
     39 
     40   tonemapScaleOffset[0] = 1.0f;
     41   tonemapScaleOffset[1] = 0.0f;
     42 }
     43 
     44 //-----------------------------------------------------------------------------
     45 Tonemapper::~Tonemapper()
     46 //-----------------------------------------------------------------------------
     47 {
     48   void* caller_context = engine_backup();
     49   engine_bind(engineContext);
     50   engine_deleteInputBuffer(tonemapTexture);
     51   engine_deleteInputBuffer(lutXformTexture);
     52   engine_deleteProgram(programID);
     53 
     54   // clear EGLImage mappings
     55   if (eglImageWrapper != 0) {
     56     delete eglImageWrapper;
     57     eglImageWrapper = 0;
     58   }
     59 
     60   engine_shutdown(engineContext);
     61   // restore the caller context
     62   engine_bind(caller_context);
     63   engine_free_backup(caller_context);
     64 }
     65 
     66 //-----------------------------------------------------------------------------
     67 Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
     68                               int lutXformSize, bool isSecure)
     69 //-----------------------------------------------------------------------------
     70 {
     71   if (colorMapSize <= 0) {
     72       ALOGE("Invalid Color Map size = %d", colorMapSize);
     73       return NULL;
     74   }
     75 
     76   // build new tonemapper
     77   Tonemapper *tonemapper = new Tonemapper();
     78 
     79   tonemapper->engineContext = engine_initialize(isSecure);
     80 
     81   void* caller_context = engine_backup();
     82   engine_bind(tonemapper->engineContext);
     83 
     84   // load the 3d lut
     85   tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
     86   tonemapper->tonemapScaleOffset[0] = ((float)(colorMapSize-1))/((float)(colorMapSize));
     87   tonemapper->tonemapScaleOffset[1] = 1.0f/(2.0f*colorMapSize);
     88 
     89   // load the non-uniform xform
     90   tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
     91   bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
     92   if( bUseXform )
     93   {
     94       tonemapper->lutXformScaleOffset[0] = ((float)(lutXformSize-1))/((float)(lutXformSize));
     95       tonemapper->lutXformScaleOffset[1] = 1.0f/(2.0f*lutXformSize);
     96   }
     97 
     98   // create the program
     99   const char *fragmentShaders[3];
    100   int fragmentShaderCount = 0;
    101   const char *version = "#version 300 es\n";
    102   const char *define = "#define USE_NONUNIFORM_SAMPLING\n";
    103 
    104   fragmentShaders[fragmentShaderCount++] = version;
    105 
    106   // non-uniform sampling
    107   if (bUseXform) {
    108     fragmentShaders[fragmentShaderCount++] = define;
    109   }
    110 
    111   if (type == TONEMAP_INVERSE) {  // inverse tonemapping
    112     fragmentShaders[fragmentShaderCount++] = rgba_inverse_tonemap_shader;
    113   } else {  // forward tonemapping
    114     fragmentShaders[fragmentShaderCount++] = forward_tonemap_shader;
    115   }
    116 
    117   tonemapper->programID =
    118       engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
    119 
    120   // restore the caller context
    121   engine_bind(caller_context);
    122   engine_free_backup(caller_context);
    123 
    124   return tonemapper;
    125 }
    126 
    127 //-----------------------------------------------------------------------------
    128 int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
    129 //-----------------------------------------------------------------------------
    130 {
    131   void* caller_context = engine_backup();
    132   // make current
    133   engine_bind(engineContext);
    134 
    135   // create eglimages if required
    136   EGLImageBuffer *dst_buffer = eglImageWrapper->wrap(dst);
    137   EGLImageBuffer *src_buffer = eglImageWrapper->wrap(src);
    138 
    139   // bind the program
    140   engine_setProgram(programID);
    141 
    142   engine_setData2f(3, tonemapScaleOffset);
    143   bool bUseXform = (lutXformTexture != 0);
    144   if( bUseXform )
    145   {
    146     engine_setData2f(4, lutXformScaleOffset);
    147   }
    148 
    149   // set destination
    150   engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
    151                         dst_buffer->getHeight());
    152   // set source
    153   engine_setExternalInputBuffer(0, src_buffer->getTexture());
    154   // set 3d lut
    155   engine_set3DInputBuffer(1, tonemapTexture);
    156   // set non-uniform xform
    157   engine_set2DInputBuffer(2, lutXformTexture);
    158 
    159   // perform
    160   int fenceFD = engine_blit(srcFenceFd);
    161 
    162   // restore the caller context
    163   engine_bind(caller_context);
    164   engine_free_backup(caller_context);
    165 
    166 
    167   return fenceFD;
    168 }
    169