blob: b18914fd5ef20f36b61c83a8cd78ba4f98f3f8a5 [file] [log] [blame]
Mathias Agopian3f844832013-08-07 21:24:32 -07001/*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H
18#define SF_RENDER_ENGINE_PROGRAMCACHE_H
19
Chia-I Wud3b13cb2018-09-13 13:31:26 -070020#include <memory>
Chia-I Wu56d7b0a2018-10-01 15:13:11 -070021#include <unordered_map>
22
Peiyong Linfb530cf2018-12-15 05:07:38 +000023#include <EGL/egl.h>
Mathias Agopian3f844832013-08-07 21:24:32 -070024#include <GLES2/gl2.h>
Peiyong Lin833074a2018-08-28 11:53:54 -070025#include <renderengine/private/Description.h>
Chia-I Wub027f802017-11-29 14:00:52 -080026#include <utils/Singleton.h>
Mathias Agopian3f844832013-08-07 21:24:32 -070027#include <utils/TypeHelpers.h>
28
Mathias Agopian3f844832013-08-07 21:24:32 -070029namespace android {
30
Peiyong Lin833074a2018-08-28 11:53:54 -070031class String8;
32
33namespace renderengine {
34
Peiyong Lin70b26ce2018-09-18 19:02:39 -070035struct Description;
Peiyong Lin833074a2018-08-28 11:53:54 -070036
37namespace gl {
38
Peiyong Lin2542cb02018-04-30 17:29:53 -070039class Formatter;
Mathias Agopian3f844832013-08-07 21:24:32 -070040class Program;
Mathias Agopian3f844832013-08-07 21:24:32 -070041
42/*
43 * This class generates GLSL programs suitable to handle a given
44 * Description. It's responsible for figuring out what to
45 * generate from a Description.
46 * It also maintains a cache of these Programs.
47 */
48class ProgramCache : public Singleton<ProgramCache> {
49public:
50 /*
51 * Key is used to retrieve a Program in the cache.
52 * A Key is generated from a Description.
53 */
54 class Key {
55 friend class ProgramCache;
56 typedef uint32_t key_t;
57 key_t mKey;
Chia-I Wub027f802017-11-29 14:00:52 -080058
Mathias Agopian3f844832013-08-07 21:24:32 -070059 public:
60 enum {
Chia-I Wu7e65bc02018-01-11 14:31:38 -080061 BLEND_SHIFT = 0,
62 BLEND_MASK = 1 << BLEND_SHIFT,
63 BLEND_PREMULT = 1 << BLEND_SHIFT,
64 BLEND_NORMAL = 0 << BLEND_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070065
Chia-I Wu7e65bc02018-01-11 14:31:38 -080066 OPACITY_SHIFT = 1,
67 OPACITY_MASK = 1 << OPACITY_SHIFT,
68 OPACITY_OPAQUE = 1 << OPACITY_SHIFT,
69 OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070070
Chia-I Wu7e65bc02018-01-11 14:31:38 -080071 ALPHA_SHIFT = 2,
72 ALPHA_MASK = 1 << ALPHA_SHIFT,
73 ALPHA_LT_ONE = 1 << ALPHA_SHIFT,
74 ALPHA_EQ_ONE = 0 << ALPHA_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -070075
Chia-I Wu7e65bc02018-01-11 14:31:38 -080076 TEXTURE_SHIFT = 3,
77 TEXTURE_MASK = 3 << TEXTURE_SHIFT,
78 TEXTURE_OFF = 0 << TEXTURE_SHIFT,
79 TEXTURE_EXT = 1 << TEXTURE_SHIFT,
80 TEXTURE_2D = 2 << TEXTURE_SHIFT,
Mathias Agopianff2ed702013-09-01 21:36:12 -070081
Lucas Dupin1b6531c2018-07-05 17:18:21 -070082 ROUNDED_CORNERS_SHIFT = 5,
83 ROUNDED_CORNERS_MASK = 1 << ROUNDED_CORNERS_SHIFT,
84 ROUNDED_CORNERS_OFF = 0 << ROUNDED_CORNERS_SHIFT,
85 ROUNDED_CORNERS_ON = 1 << ROUNDED_CORNERS_SHIFT,
86
87 INPUT_TRANSFORM_MATRIX_SHIFT = 6,
Peiyong Lina296b0c2018-04-30 16:55:29 -070088 INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
89 INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT,
90 INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
Romain Guy88d37dd2017-05-26 17:57:05 -070091
Lucas Dupin1b6531c2018-07-05 17:18:21 -070092 OUTPUT_TRANSFORM_MATRIX_SHIFT = 7,
Peiyong Lina296b0c2018-04-30 16:55:29 -070093 OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
94 OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
95 OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
96
Lucas Dupin1b6531c2018-07-05 17:18:21 -070097 INPUT_TF_SHIFT = 8,
Chia-I Wu7e65bc02018-01-11 14:31:38 -080098 INPUT_TF_MASK = 3 << INPUT_TF_SHIFT,
99 INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
100 INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800101 INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
Peiyong Lina3fb7d62018-04-11 17:41:47 -0700102 INPUT_TF_HLG = 3 << INPUT_TF_SHIFT,
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800103
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700104 OUTPUT_TF_SHIFT = 10,
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800105 OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
106 OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
107 OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800108 OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
Peiyong Lina3fb7d62018-04-11 17:41:47 -0700109 OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT,
Chia-I Wu131d3762018-01-11 14:35:27 -0800110
Vishnu Nair16efdbf2019-12-10 11:55:42 -0800111 SHADOW_SHIFT = 13,
112 SHADOW_MASK = 1 << SHADOW_SHIFT,
113 SHADOW_OFF = 0 << SHADOW_SHIFT,
114 SHADOW_ON = 1 << SHADOW_SHIFT,
KaiChieh Chuang436fc192020-09-07 13:48:42 +0800115
116 DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT = 14,
117 DISPLAY_COLOR_TRANSFORM_MATRIX_MASK = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
118 DISPLAY_COLOR_TRANSFORM_MATRIX_OFF = 0 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
119 DISPLAY_COLOR_TRANSFORM_MATRIX_ON = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -0700120 };
121
Chia-I Wub027f802017-11-29 14:00:52 -0800122 inline Key() : mKey(0) {}
123 inline Key(const Key& rhs) : mKey(rhs.mKey) {}
Mathias Agopian3f844832013-08-07 21:24:32 -0700124
125 inline Key& set(key_t mask, key_t value) {
126 mKey = (mKey & ~mask) | value;
127 return *this;
128 }
129
Chia-I Wub027f802017-11-29 14:00:52 -0800130 inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
Vishnu Nairf19544f2020-02-03 11:23:26 -0800131 inline bool hasTextureCoords() const { return isTexturing() && !drawShadows(); }
Chia-I Wub027f802017-11-29 14:00:52 -0800132 inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
133 inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
134 inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
135 inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700136 inline bool hasRoundedCorners() const {
137 return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON;
138 }
Vishnu Nair16efdbf2019-12-10 11:55:42 -0800139 inline bool drawShadows() const { return (mKey & SHADOW_MASK) == SHADOW_ON; }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700140 inline bool hasInputTransformMatrix() const {
141 return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON;
142 }
143 inline bool hasOutputTransformMatrix() const {
144 return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
145 }
KaiChieh Chuang436fc192020-09-07 13:48:42 +0800146 inline bool hasDisplayColorMatrix() const {
147 return (mKey & DISPLAY_COLOR_TRANSFORM_MATRIX_MASK) ==
148 DISPLAY_COLOR_TRANSFORM_MATRIX_ON;
149 }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700150 inline bool hasTransformMatrix() const {
151 return hasInputTransformMatrix() || hasOutputTransformMatrix();
152 }
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800153 inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
154 inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
Peiyong Lin53f320e2018-04-23 17:31:06 -0700155
156 // When HDR and non-HDR contents are mixed, or different types of HDR contents are
157 // mixed, we will do a tone mapping process to tone map the input content to output
158 // content. Currently, the following conversions handled, they are:
159 // * SDR -> HLG
160 // * SDR -> PQ
161 // * HLG -> PQ
162 inline bool needsToneMapping() const {
163 int inputTF = getInputTF();
164 int outputTF = getOutputTF();
165
166 // Return false when converting from SDR to SDR.
167 if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
168 return false;
169 }
170 if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
171 return false;
172 }
173
174 inputTF >>= Key::INPUT_TF_SHIFT;
175 outputTF >>= Key::OUTPUT_TF_SHIFT;
176 return inputTF != outputTF;
177 }
Mathias Agopian3f844832013-08-07 21:24:32 -0700178
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700179 // for use by std::unordered_map
180
Peiyong Lin46080ef2018-10-26 18:43:14 -0700181 bool operator==(const Key& other) const { return mKey == other.mKey; }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700182
183 struct Hash {
Peiyong Lin46080ef2018-10-26 18:43:14 -0700184 size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700185 };
Mathias Agopian3f844832013-08-07 21:24:32 -0700186 };
187
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700188 ProgramCache() = default;
189 ~ProgramCache() = default;
Mathias Agopian3f844832013-08-07 21:24:32 -0700190
Chia-I Wu93e14df2018-06-04 10:10:17 -0700191 // Generate shaders to populate the cache
Chong Zhang8ddb04e2019-10-02 14:20:02 -0700192 void primeCache(const EGLContext context, bool useColorManagement, bool toneMapperShaderOnly);
Chia-I Wu93e14df2018-06-04 10:10:17 -0700193
Peiyong Linfb530cf2018-12-15 05:07:38 +0000194 size_t getSize(const EGLContext context) { return mCaches[context].size(); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700195
Mathias Agopian3f844832013-08-07 21:24:32 -0700196 // useProgram lookup a suitable program in the cache or generates one
197 // if none can be found.
Peiyong Linfb530cf2018-12-15 05:07:38 +0000198 void useProgram(const EGLContext context, const Description& description);
Mathias Agopian3f844832013-08-07 21:24:32 -0700199
Alec Mouri2725c092020-11-25 09:53:56 -0800200 void purgeCaches() { mCaches.clear(); }
201
Mathias Agopian3f844832013-08-07 21:24:32 -0700202private:
Mathias Agopian3f844832013-08-07 21:24:32 -0700203 // compute a cache Key from a Description
204 static Key computeKey(const Description& description);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700205 // Generate EOTF based from Key.
206 static void generateEOTF(Formatter& fs, const Key& needs);
Peiyong Lin53f320e2018-04-23 17:31:06 -0700207 // Generate necessary tone mapping methods for OOTF.
208 static void generateToneMappingProcess(Formatter& fs, const Key& needs);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700209 // Generate OOTF based from Key.
210 static void generateOOTF(Formatter& fs, const Key& needs);
211 // Generate OETF based from Key.
212 static void generateOETF(Formatter& fs, const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700213 // generates a program from the Key
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700214 static std::unique_ptr<Program> generateProgram(const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700215 // generates the vertex shader from the Key
216 static String8 generateVertexShader(const Key& needs);
217 // generates the fragment shader from the Key
218 static String8 generateFragmentShader(const Key& needs);
219
220 // Key/Value map used for caching Programs. Currently the cache
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700221 // is never shrunk (and the GL program objects are never deleted).
Peiyong Linfb530cf2018-12-15 05:07:38 +0000222 std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>>
223 mCaches;
Mathias Agopian3f844832013-08-07 21:24:32 -0700224};
225
Peiyong Lin46080ef2018-10-26 18:43:14 -0700226} // namespace gl
227} // namespace renderengine
Mathias Agopian3f844832013-08-07 21:24:32 -0700228
Peiyong Lin833074a2018-08-28 11:53:54 -0700229ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key)
230
Peiyong Lin46080ef2018-10-26 18:43:14 -0700231} // namespace android
Mathias Agopian3f844832013-08-07 21:24:32 -0700232
233#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */