1 /*
2 * Copyright (c) 2016-2019, 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 engine_bind(engineContext);
49 engine_deleteInputBuffer(tonemapTexture);
50 engine_deleteInputBuffer(lutXformTexture);
51 engine_deleteProgram(programID);
52
53 // clear EGLImage mappings
54 if (eglImageWrapper != 0) {
55 delete eglImageWrapper;
56 eglImageWrapper = 0;
57 }
58
59 engine_shutdown(engineContext);
60 }
61
62 //-----------------------------------------------------------------------------
build(int type,void * colorMap,int colorMapSize,void * lutXform,int lutXformSize,bool isSecure)63 Tonemapper *Tonemapper::build(int type, void *colorMap, int colorMapSize, void *lutXform,
64 int lutXformSize, bool isSecure)
65 //-----------------------------------------------------------------------------
66 {
67 if (colorMapSize <= 0) {
68 ALOGE("Invalid Color Map size = %d", colorMapSize);
69 return NULL;
70 }
71
72 // build new tonemapper
73 Tonemapper *tonemapper = new Tonemapper();
74
75 tonemapper->engineContext = engine_initialize(isSecure);
76
77 engine_bind(tonemapper->engineContext);
78
79 // load the 3d lut
80 tonemapper->tonemapTexture = engine_load3DTexture(colorMap, colorMapSize, 0);
81 tonemapper->tonemapScaleOffset[0] = ((float)(colorMapSize-1))/((float)(colorMapSize));
82 tonemapper->tonemapScaleOffset[1] = 1.0f/(2.0f*colorMapSize);
83
84 // load the non-uniform xform
85 tonemapper->lutXformTexture = engine_load1DTexture(lutXform, lutXformSize, 0);
86 bool bUseXform = (tonemapper->lutXformTexture != 0) && (lutXformSize != 0);
87 if( bUseXform )
88 {
89 tonemapper->lutXformScaleOffset[0] = ((float)(lutXformSize-1))/((float)(lutXformSize));
90 tonemapper->lutXformScaleOffset[1] = 1.0f/(2.0f*lutXformSize);
91 }
92
93 // create the program
94 const char *fragmentShaders[3];
95 int fragmentShaderCount = 0;
96 const char *version = "#version 300 es\n";
97 const char *define = "#define USE_NONUNIFORM_SAMPLING\n";
98
99 fragmentShaders[fragmentShaderCount++] = version;
100
101 // non-uniform sampling
102 if (bUseXform) {
103 fragmentShaders[fragmentShaderCount++] = define;
104 }
105
106 if (type == TONEMAP_INVERSE) { // inverse tonemapping
107 fragmentShaders[fragmentShaderCount++] = rgba_inverse_tonemap_shader;
108 } else { // forward tonemapping
109 fragmentShaders[fragmentShaderCount++] = forward_tonemap_shader;
110 }
111
112 tonemapper->programID =
113 engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
114
115 return tonemapper;
116 }
117
118 //-----------------------------------------------------------------------------
blit(const void * dst,const void * src,int srcFenceFd)119 int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
120 //-----------------------------------------------------------------------------
121 {
122 // make current
123 engine_bind(engineContext);
124
125 // create eglimages if required
126 EGLImageBuffer *dst_buffer = eglImageWrapper->wrap(dst);
127 EGLImageBuffer *src_buffer = eglImageWrapper->wrap(src);
128
129 // bind the program
130 engine_setProgram(programID);
131
132 engine_setData2f(3, tonemapScaleOffset);
133 bool bUseXform = (lutXformTexture != 0);
134 if( bUseXform )
135 {
136 engine_setData2f(4, lutXformScaleOffset);
137 }
138
139 // set destination
140 if (dst_buffer) {
141 engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
142 dst_buffer->getHeight());
143 }
144 // set source
145 if (src_buffer) {
146 engine_setExternalInputBuffer(0, src_buffer->getTexture(0x8D65 /* target texture */));
147 }
148 // set 3d lut
149 engine_set3DInputBuffer(1, tonemapTexture);
150 // set non-uniform xform
151 engine_set2DInputBuffer(2, lutXformTexture);
152
153 // perform
154 int fenceFD = engine_blit(srcFenceFd);
155
156 return fenceFD;
157 }
158