blob: 535d21cd5215b21a4b5fad6de8900ab28fa58c8c [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
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700111 Y410_BT2020_SHIFT = 12,
Chia-I Wu131d3762018-01-11 14:35:27 -0800112 Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT,
113 Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT,
114 Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT,
Vishnu Nair16efdbf2019-12-10 11:55:42 -0800115
116 SHADOW_SHIFT = 13,
117 SHADOW_MASK = 1 << SHADOW_SHIFT,
118 SHADOW_OFF = 0 << SHADOW_SHIFT,
119 SHADOW_ON = 1 << SHADOW_SHIFT,
KaiChieh Chuang436fc192020-09-07 13:48:42 +0800120
121 DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT = 14,
122 DISPLAY_COLOR_TRANSFORM_MATRIX_MASK = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
123 DISPLAY_COLOR_TRANSFORM_MATRIX_OFF = 0 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
124 DISPLAY_COLOR_TRANSFORM_MATRIX_ON = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
Mathias Agopian3f844832013-08-07 21:24:32 -0700125 };
126
Chia-I Wub027f802017-11-29 14:00:52 -0800127 inline Key() : mKey(0) {}
128 inline Key(const Key& rhs) : mKey(rhs.mKey) {}
Mathias Agopian3f844832013-08-07 21:24:32 -0700129
130 inline Key& set(key_t mask, key_t value) {
131 mKey = (mKey & ~mask) | value;
132 return *this;
133 }
134
Chia-I Wub027f802017-11-29 14:00:52 -0800135 inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
Vishnu Nairf19544f2020-02-03 11:23:26 -0800136 inline bool hasTextureCoords() const { return isTexturing() && !drawShadows(); }
Chia-I Wub027f802017-11-29 14:00:52 -0800137 inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
138 inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
139 inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
140 inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
Lucas Dupin1b6531c2018-07-05 17:18:21 -0700141 inline bool hasRoundedCorners() const {
142 return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON;
143 }
Vishnu Nair16efdbf2019-12-10 11:55:42 -0800144 inline bool drawShadows() const { return (mKey & SHADOW_MASK) == SHADOW_ON; }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700145 inline bool hasInputTransformMatrix() const {
146 return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON;
147 }
148 inline bool hasOutputTransformMatrix() const {
149 return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
150 }
KaiChieh Chuang436fc192020-09-07 13:48:42 +0800151 inline bool hasDisplayColorMatrix() const {
152 return (mKey & DISPLAY_COLOR_TRANSFORM_MATRIX_MASK) ==
153 DISPLAY_COLOR_TRANSFORM_MATRIX_ON;
154 }
Peiyong Lina296b0c2018-04-30 16:55:29 -0700155 inline bool hasTransformMatrix() const {
156 return hasInputTransformMatrix() || hasOutputTransformMatrix();
157 }
Chia-I Wu7e65bc02018-01-11 14:31:38 -0800158 inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
159 inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
Peiyong Lin53f320e2018-04-23 17:31:06 -0700160
161 // When HDR and non-HDR contents are mixed, or different types of HDR contents are
162 // mixed, we will do a tone mapping process to tone map the input content to output
163 // content. Currently, the following conversions handled, they are:
164 // * SDR -> HLG
165 // * SDR -> PQ
166 // * HLG -> PQ
167 inline bool needsToneMapping() const {
168 int inputTF = getInputTF();
169 int outputTF = getOutputTF();
170
171 // Return false when converting from SDR to SDR.
172 if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
173 return false;
174 }
175 if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
176 return false;
177 }
178
179 inputTF >>= Key::INPUT_TF_SHIFT;
180 outputTF >>= Key::OUTPUT_TF_SHIFT;
181 return inputTF != outputTF;
182 }
Chia-I Wu131d3762018-01-11 14:35:27 -0800183 inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
Mathias Agopian3f844832013-08-07 21:24:32 -0700184
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700185 // for use by std::unordered_map
186
Peiyong Lin46080ef2018-10-26 18:43:14 -0700187 bool operator==(const Key& other) const { return mKey == other.mKey; }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700188
189 struct Hash {
Peiyong Lin46080ef2018-10-26 18:43:14 -0700190 size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700191 };
Mathias Agopian3f844832013-08-07 21:24:32 -0700192 };
193
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700194 ProgramCache() = default;
195 ~ProgramCache() = default;
Mathias Agopian3f844832013-08-07 21:24:32 -0700196
Chia-I Wu93e14df2018-06-04 10:10:17 -0700197 // Generate shaders to populate the cache
Chong Zhang8ddb04e2019-10-02 14:20:02 -0700198 void primeCache(const EGLContext context, bool useColorManagement, bool toneMapperShaderOnly);
Chia-I Wu93e14df2018-06-04 10:10:17 -0700199
Peiyong Linfb530cf2018-12-15 05:07:38 +0000200 size_t getSize(const EGLContext context) { return mCaches[context].size(); }
Chia-I Wu56d7b0a2018-10-01 15:13:11 -0700201
Mathias Agopian3f844832013-08-07 21:24:32 -0700202 // useProgram lookup a suitable program in the cache or generates one
203 // if none can be found.
Peiyong Linfb530cf2018-12-15 05:07:38 +0000204 void useProgram(const EGLContext context, const Description& description);
Mathias Agopian3f844832013-08-07 21:24:32 -0700205
Alec Mouri2725c092020-11-25 09:53:56 -0800206 void purgeCaches() { mCaches.clear(); }
207
Mathias Agopian3f844832013-08-07 21:24:32 -0700208private:
Mathias Agopian3f844832013-08-07 21:24:32 -0700209 // compute a cache Key from a Description
210 static Key computeKey(const Description& description);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700211 // Generate EOTF based from Key.
212 static void generateEOTF(Formatter& fs, const Key& needs);
Peiyong Lin53f320e2018-04-23 17:31:06 -0700213 // Generate necessary tone mapping methods for OOTF.
214 static void generateToneMappingProcess(Formatter& fs, const Key& needs);
Peiyong Lin2542cb02018-04-30 17:29:53 -0700215 // Generate OOTF based from Key.
216 static void generateOOTF(Formatter& fs, const Key& needs);
217 // Generate OETF based from Key.
218 static void generateOETF(Formatter& fs, const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700219 // generates a program from the Key
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700220 static std::unique_ptr<Program> generateProgram(const Key& needs);
Mathias Agopian3f844832013-08-07 21:24:32 -0700221 // generates the vertex shader from the Key
222 static String8 generateVertexShader(const Key& needs);
223 // generates the fragment shader from the Key
224 static String8 generateFragmentShader(const Key& needs);
225
226 // Key/Value map used for caching Programs. Currently the cache
Chia-I Wud3b13cb2018-09-13 13:31:26 -0700227 // is never shrunk (and the GL program objects are never deleted).
Peiyong Linfb530cf2018-12-15 05:07:38 +0000228 std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>>
229 mCaches;
Mathias Agopian3f844832013-08-07 21:24:32 -0700230};
231
Peiyong Lin46080ef2018-10-26 18:43:14 -0700232} // namespace gl
233} // namespace renderengine
Mathias Agopian3f844832013-08-07 21:24:32 -0700234
Peiyong Lin833074a2018-08-28 11:53:54 -0700235ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key)
236
Peiyong Lin46080ef2018-10-26 18:43:14 -0700237} // namespace android
Mathias Agopian3f844832013-08-07 21:24:32 -0700238
239#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */