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 //-----------------------------------------------------------------------------
Tonemapper()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 //-----------------------------------------------------------------------------
~Tonemapper()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 //-----------------------------------------------------------------------------
build(int type,void * colorMap,int colorMapSize,void * lutXform,int lutXformSize,bool isSecure)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 //-----------------------------------------------------------------------------
blit(const void * dst,const void * src,int srcFenceFd)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